lib80211: absorb crypto bits from net/ieee80211
These bits are shared already between ipw2x00 and hostap, and could probably be shared both more cleanly and with other drivers. This commit simply relocates the code to lib80211 and adjusts the drivers appropriately. Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
dfe1bafdba
commit
274bfb8dc5
|
@ -2,8 +2,10 @@ config HOSTAP
|
||||||
tristate "IEEE 802.11 for Host AP (Prism2/2.5/3 and WEP/TKIP/CCMP)"
|
tristate "IEEE 802.11 for Host AP (Prism2/2.5/3 and WEP/TKIP/CCMP)"
|
||||||
depends on WLAN_80211
|
depends on WLAN_80211
|
||||||
select WIRELESS_EXT
|
select WIRELESS_EXT
|
||||||
select IEEE80211
|
select LIB80211
|
||||||
select IEEE80211_CRYPT_WEP
|
select LIB80211_CRYPT_WEP
|
||||||
|
select LIB80211_CRYPT_TKIP
|
||||||
|
select LIB80211_CRYPT_CCMP
|
||||||
---help---
|
---help---
|
||||||
Shared driver code for IEEE 802.11b wireless cards based on
|
Shared driver code for IEEE 802.11b wireless cards based on
|
||||||
Intersil Prism2/2.5/3 chipset. This driver supports so called
|
Intersil Prism2/2.5/3 chipset. This driver supports so called
|
||||||
|
|
|
@ -63,7 +63,7 @@ void ap_control_flush_macs(struct mac_restrictions *mac_restrictions);
|
||||||
int ap_control_kick_mac(struct ap_data *ap, struct net_device *dev, u8 *mac);
|
int ap_control_kick_mac(struct ap_data *ap, struct net_device *dev, u8 *mac);
|
||||||
void ap_control_kickall(struct ap_data *ap);
|
void ap_control_kickall(struct ap_data *ap);
|
||||||
void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent,
|
void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent,
|
||||||
struct ieee80211_crypt_data ***crypt);
|
struct lib80211_crypt_data ***crypt);
|
||||||
int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[],
|
int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[],
|
||||||
struct iw_quality qual[], int buf_size,
|
struct iw_quality qual[], int buf_size,
|
||||||
int aplist);
|
int aplist);
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#define HOSTAP_80211_H
|
#define HOSTAP_80211_H
|
||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <net/ieee80211_crypt.h>
|
#include <net/ieee80211.h>
|
||||||
|
|
||||||
struct hostap_ieee80211_mgmt {
|
struct hostap_ieee80211_mgmt {
|
||||||
__le16 frame_control;
|
__le16 frame_control;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#include <linux/etherdevice.h>
|
#include <linux/etherdevice.h>
|
||||||
#include <net/ieee80211_crypt.h>
|
#include <net/lib80211.h>
|
||||||
|
|
||||||
#include "hostap_80211.h"
|
#include "hostap_80211.h"
|
||||||
#include "hostap.h"
|
#include "hostap.h"
|
||||||
|
@ -649,7 +649,7 @@ static int hostap_is_eapol_frame(local_info_t *local, struct sk_buff *skb)
|
||||||
/* Called only as a tasklet (software IRQ) */
|
/* Called only as a tasklet (software IRQ) */
|
||||||
static int
|
static int
|
||||||
hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb,
|
hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb,
|
||||||
struct ieee80211_crypt_data *crypt)
|
struct lib80211_crypt_data *crypt)
|
||||||
{
|
{
|
||||||
struct ieee80211_hdr_4addr *hdr;
|
struct ieee80211_hdr_4addr *hdr;
|
||||||
int res, hdrlen;
|
int res, hdrlen;
|
||||||
|
@ -687,7 +687,7 @@ hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb,
|
||||||
/* Called only as a tasklet (software IRQ) */
|
/* Called only as a tasklet (software IRQ) */
|
||||||
static int
|
static int
|
||||||
hostap_rx_frame_decrypt_msdu(local_info_t *local, struct sk_buff *skb,
|
hostap_rx_frame_decrypt_msdu(local_info_t *local, struct sk_buff *skb,
|
||||||
int keyidx, struct ieee80211_crypt_data *crypt)
|
int keyidx, struct lib80211_crypt_data *crypt)
|
||||||
{
|
{
|
||||||
struct ieee80211_hdr_4addr *hdr;
|
struct ieee80211_hdr_4addr *hdr;
|
||||||
int res, hdrlen;
|
int res, hdrlen;
|
||||||
|
@ -733,7 +733,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
|
||||||
int from_assoc_ap = 0;
|
int from_assoc_ap = 0;
|
||||||
u8 dst[ETH_ALEN];
|
u8 dst[ETH_ALEN];
|
||||||
u8 src[ETH_ALEN];
|
u8 src[ETH_ALEN];
|
||||||
struct ieee80211_crypt_data *crypt = NULL;
|
struct lib80211_crypt_data *crypt = NULL;
|
||||||
void *sta = NULL;
|
void *sta = NULL;
|
||||||
int keyidx = 0;
|
int keyidx = 0;
|
||||||
|
|
||||||
|
@ -785,7 +785,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
if (skb->len >= hdrlen + 3)
|
if (skb->len >= hdrlen + 3)
|
||||||
idx = skb->data[hdrlen + 3] >> 6;
|
idx = skb->data[hdrlen + 3] >> 6;
|
||||||
crypt = local->crypt[idx];
|
crypt = local->crypt_info.crypt[idx];
|
||||||
sta = NULL;
|
sta = NULL;
|
||||||
|
|
||||||
/* Use station specific key to override default keys if the
|
/* Use station specific key to override default keys if the
|
||||||
|
|
|
@ -306,7 +306,7 @@ int hostap_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||||
|
|
||||||
/* Called only from software IRQ */
|
/* Called only from software IRQ */
|
||||||
static struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb,
|
static struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb,
|
||||||
struct ieee80211_crypt_data *crypt)
|
struct lib80211_crypt_data *crypt)
|
||||||
{
|
{
|
||||||
struct hostap_interface *iface;
|
struct hostap_interface *iface;
|
||||||
local_info_t *local;
|
local_info_t *local;
|
||||||
|
@ -405,7 +405,7 @@ int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||||
if (local->host_encrypt) {
|
if (local->host_encrypt) {
|
||||||
/* Set crypt to default algorithm and key; will be replaced in
|
/* Set crypt to default algorithm and key; will be replaced in
|
||||||
* AP code if STA has own alg/key */
|
* AP code if STA has own alg/key */
|
||||||
tx.crypt = local->crypt[local->tx_keyidx];
|
tx.crypt = local->crypt_info.crypt[local->crypt_info.tx_keyidx];
|
||||||
tx.host_encrypt = 1;
|
tx.host_encrypt = 1;
|
||||||
} else {
|
} else {
|
||||||
tx.crypt = NULL;
|
tx.crypt = NULL;
|
||||||
|
@ -487,7 +487,9 @@ int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||||
|
|
||||||
if (tx.crypt && (!tx.crypt->ops || !tx.crypt->ops->encrypt_mpdu))
|
if (tx.crypt && (!tx.crypt->ops || !tx.crypt->ops->encrypt_mpdu))
|
||||||
tx.crypt = NULL;
|
tx.crypt = NULL;
|
||||||
else if ((tx.crypt || local->crypt[local->tx_keyidx]) && !no_encrypt) {
|
else if ((tx.crypt ||
|
||||||
|
local->crypt_info.crypt[local->crypt_info.tx_keyidx]) &&
|
||||||
|
!no_encrypt) {
|
||||||
/* Add ISWEP flag both for firmware and host based encryption
|
/* Add ISWEP flag both for firmware and host based encryption
|
||||||
*/
|
*/
|
||||||
fc |= IEEE80211_FCTL_PROTECTED;
|
fc |= IEEE80211_FCTL_PROTECTED;
|
||||||
|
|
|
@ -1206,7 +1206,7 @@ static void prism2_check_tx_rates(struct sta_info *sta)
|
||||||
|
|
||||||
static void ap_crypt_init(struct ap_data *ap)
|
static void ap_crypt_init(struct ap_data *ap)
|
||||||
{
|
{
|
||||||
ap->crypt = ieee80211_get_crypto_ops("WEP");
|
ap->crypt = lib80211_get_crypto_ops("WEP");
|
||||||
|
|
||||||
if (ap->crypt) {
|
if (ap->crypt) {
|
||||||
if (ap->crypt->init) {
|
if (ap->crypt->init) {
|
||||||
|
@ -1224,7 +1224,7 @@ static void ap_crypt_init(struct ap_data *ap)
|
||||||
|
|
||||||
if (ap->crypt == NULL) {
|
if (ap->crypt == NULL) {
|
||||||
printk(KERN_WARNING "AP could not initialize WEP: load module "
|
printk(KERN_WARNING "AP could not initialize WEP: load module "
|
||||||
"ieee80211_crypt_wep.ko\n");
|
"lib80211_crypt_wep.ko\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1293,7 +1293,7 @@ static void handle_authen(local_info_t *local, struct sk_buff *skb,
|
||||||
__le16 *pos;
|
__le16 *pos;
|
||||||
u16 resp = WLAN_STATUS_SUCCESS, fc;
|
u16 resp = WLAN_STATUS_SUCCESS, fc;
|
||||||
struct sta_info *sta = NULL;
|
struct sta_info *sta = NULL;
|
||||||
struct ieee80211_crypt_data *crypt;
|
struct lib80211_crypt_data *crypt;
|
||||||
char *txt = "";
|
char *txt = "";
|
||||||
|
|
||||||
len = skb->len - IEEE80211_MGMT_HDR_LEN;
|
len = skb->len - IEEE80211_MGMT_HDR_LEN;
|
||||||
|
@ -1319,7 +1319,7 @@ static void handle_authen(local_info_t *local, struct sk_buff *skb,
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
if (skb->len >= hdrlen + 3)
|
if (skb->len >= hdrlen + 3)
|
||||||
idx = skb->data[hdrlen + 3] >> 6;
|
idx = skb->data[hdrlen + 3] >> 6;
|
||||||
crypt = local->crypt[idx];
|
crypt = local->crypt_info.crypt[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
pos = (__le16 *) (skb->data + IEEE80211_MGMT_HDR_LEN);
|
pos = (__le16 *) (skb->data + IEEE80211_MGMT_HDR_LEN);
|
||||||
|
@ -3065,7 +3065,7 @@ ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev,
|
||||||
/* Called only as a tasklet (software IRQ) */
|
/* Called only as a tasklet (software IRQ) */
|
||||||
int hostap_handle_sta_crypto(local_info_t *local,
|
int hostap_handle_sta_crypto(local_info_t *local,
|
||||||
struct ieee80211_hdr_4addr *hdr,
|
struct ieee80211_hdr_4addr *hdr,
|
||||||
struct ieee80211_crypt_data **crypt,
|
struct lib80211_crypt_data **crypt,
|
||||||
void **sta_ptr)
|
void **sta_ptr)
|
||||||
{
|
{
|
||||||
struct sta_info *sta;
|
struct sta_info *sta;
|
||||||
|
@ -3213,7 +3213,7 @@ void hostap_update_rates(local_info_t *local)
|
||||||
|
|
||||||
|
|
||||||
void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent,
|
void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent,
|
||||||
struct ieee80211_crypt_data ***crypt)
|
struct lib80211_crypt_data ***crypt)
|
||||||
{
|
{
|
||||||
struct sta_info *sta;
|
struct sta_info *sta;
|
||||||
|
|
||||||
|
|
|
@ -74,7 +74,7 @@ struct sta_info {
|
||||||
u32 tx_since_last_failure;
|
u32 tx_since_last_failure;
|
||||||
u32 tx_consecutive_exc;
|
u32 tx_consecutive_exc;
|
||||||
|
|
||||||
struct ieee80211_crypt_data *crypt;
|
struct lib80211_crypt_data *crypt;
|
||||||
|
|
||||||
int ap; /* whether this station is an AP */
|
int ap; /* whether this station is an AP */
|
||||||
|
|
||||||
|
@ -209,7 +209,7 @@ struct ap_data {
|
||||||
|
|
||||||
/* WEP operations for generating challenges to be used with shared key
|
/* WEP operations for generating challenges to be used with shared key
|
||||||
* authentication */
|
* authentication */
|
||||||
struct ieee80211_crypto_ops *crypt;
|
struct lib80211_crypto_ops *crypt;
|
||||||
void *crypt_priv;
|
void *crypt_priv;
|
||||||
#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
|
#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
|
||||||
};
|
};
|
||||||
|
@ -229,7 +229,7 @@ typedef enum {
|
||||||
struct hostap_tx_data {
|
struct hostap_tx_data {
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
int host_encrypt;
|
int host_encrypt;
|
||||||
struct ieee80211_crypt_data *crypt;
|
struct lib80211_crypt_data *crypt;
|
||||||
void *sta_ptr;
|
void *sta_ptr;
|
||||||
};
|
};
|
||||||
ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx);
|
ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx);
|
||||||
|
@ -244,7 +244,7 @@ ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev,
|
||||||
struct hostap_80211_rx_status *rx_stats,
|
struct hostap_80211_rx_status *rx_stats,
|
||||||
int wds);
|
int wds);
|
||||||
int hostap_handle_sta_crypto(local_info_t *local, struct ieee80211_hdr_4addr *hdr,
|
int hostap_handle_sta_crypto(local_info_t *local, struct ieee80211_hdr_4addr *hdr,
|
||||||
struct ieee80211_crypt_data **crypt,
|
struct lib80211_crypt_data **crypt,
|
||||||
void **sta_ptr);
|
void **sta_ptr);
|
||||||
int hostap_is_sta_assoc(struct ap_data *ap, u8 *sta_addr);
|
int hostap_is_sta_assoc(struct ap_data *ap, u8 *sta_addr);
|
||||||
int hostap_is_sta_authorized(struct ap_data *ap, u8 *sta_addr);
|
int hostap_is_sta_authorized(struct ap_data *ap, u8 *sta_addr);
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
#include <linux/wireless.h>
|
#include <linux/wireless.h>
|
||||||
#include <net/iw_handler.h>
|
#include <net/iw_handler.h>
|
||||||
#include <net/ieee80211.h>
|
#include <net/ieee80211.h>
|
||||||
#include <net/ieee80211_crypt.h>
|
#include <net/lib80211.h>
|
||||||
#include <asm/irq.h>
|
#include <asm/irq.h>
|
||||||
|
|
||||||
#include "hostap_80211.h"
|
#include "hostap_80211.h"
|
||||||
|
@ -2791,11 +2791,12 @@ static void prism2_check_sta_fw_version(local_info_t *local)
|
||||||
static void prism2_crypt_deinit_entries(local_info_t *local, int force)
|
static void prism2_crypt_deinit_entries(local_info_t *local, int force)
|
||||||
{
|
{
|
||||||
struct list_head *ptr, *n;
|
struct list_head *ptr, *n;
|
||||||
struct ieee80211_crypt_data *entry;
|
struct lib80211_crypt_data *entry;
|
||||||
|
|
||||||
for (ptr = local->crypt_deinit_list.next, n = ptr->next;
|
for (ptr = local->crypt_info.crypt_deinit_list.next, n = ptr->next;
|
||||||
ptr != &local->crypt_deinit_list; ptr = n, n = ptr->next) {
|
ptr != &local->crypt_info.crypt_deinit_list;
|
||||||
entry = list_entry(ptr, struct ieee80211_crypt_data, list);
|
ptr = n, n = ptr->next) {
|
||||||
|
entry = list_entry(ptr, struct lib80211_crypt_data, list);
|
||||||
|
|
||||||
if (atomic_read(&entry->refcnt) != 0 && !force)
|
if (atomic_read(&entry->refcnt) != 0 && !force)
|
||||||
continue;
|
continue;
|
||||||
|
@ -2816,11 +2817,11 @@ static void prism2_crypt_deinit_handler(unsigned long data)
|
||||||
|
|
||||||
spin_lock_irqsave(&local->lock, flags);
|
spin_lock_irqsave(&local->lock, flags);
|
||||||
prism2_crypt_deinit_entries(local, 0);
|
prism2_crypt_deinit_entries(local, 0);
|
||||||
if (!list_empty(&local->crypt_deinit_list)) {
|
if (!list_empty(&local->crypt_info.crypt_deinit_list)) {
|
||||||
printk(KERN_DEBUG "%s: entries remaining in delayed crypt "
|
printk(KERN_DEBUG "%s: entries remaining in delayed crypt "
|
||||||
"deletion list\n", local->dev->name);
|
"deletion list\n", local->dev->name);
|
||||||
local->crypt_deinit_timer.expires = jiffies + HZ;
|
local->crypt_info.crypt_deinit_timer.expires = jiffies + HZ;
|
||||||
add_timer(&local->crypt_deinit_timer);
|
add_timer(&local->crypt_info.crypt_deinit_timer);
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&local->lock, flags);
|
spin_unlock_irqrestore(&local->lock, flags);
|
||||||
|
|
||||||
|
@ -3250,10 +3251,13 @@ while (0)
|
||||||
|
|
||||||
INIT_LIST_HEAD(&local->cmd_queue);
|
INIT_LIST_HEAD(&local->cmd_queue);
|
||||||
init_waitqueue_head(&local->hostscan_wq);
|
init_waitqueue_head(&local->hostscan_wq);
|
||||||
INIT_LIST_HEAD(&local->crypt_deinit_list);
|
|
||||||
init_timer(&local->crypt_deinit_timer);
|
local->crypt_info.name = dev->name;
|
||||||
local->crypt_deinit_timer.data = (unsigned long) local;
|
local->crypt_info.lock = &local->lock;
|
||||||
local->crypt_deinit_timer.function = prism2_crypt_deinit_handler;
|
INIT_LIST_HEAD(&local->crypt_info.crypt_deinit_list);
|
||||||
|
init_timer(&local->crypt_info.crypt_deinit_timer);
|
||||||
|
local->crypt_info.crypt_deinit_timer.data = (unsigned long) local;
|
||||||
|
local->crypt_info.crypt_deinit_timer.function = prism2_crypt_deinit_handler;
|
||||||
|
|
||||||
init_timer(&local->passive_scan_timer);
|
init_timer(&local->passive_scan_timer);
|
||||||
local->passive_scan_timer.data = (unsigned long) local;
|
local->passive_scan_timer.data = (unsigned long) local;
|
||||||
|
@ -3354,8 +3358,8 @@ static void prism2_free_local_data(struct net_device *dev)
|
||||||
|
|
||||||
flush_scheduled_work();
|
flush_scheduled_work();
|
||||||
|
|
||||||
if (timer_pending(&local->crypt_deinit_timer))
|
if (timer_pending(&local->crypt_info.crypt_deinit_timer))
|
||||||
del_timer(&local->crypt_deinit_timer);
|
del_timer(&local->crypt_info.crypt_deinit_timer);
|
||||||
prism2_crypt_deinit_entries(local, 1);
|
prism2_crypt_deinit_entries(local, 1);
|
||||||
|
|
||||||
if (timer_pending(&local->passive_scan_timer))
|
if (timer_pending(&local->passive_scan_timer))
|
||||||
|
@ -3374,12 +3378,12 @@ static void prism2_free_local_data(struct net_device *dev)
|
||||||
prism2_callback(local, PRISM2_CALLBACK_DISABLE);
|
prism2_callback(local, PRISM2_CALLBACK_DISABLE);
|
||||||
|
|
||||||
for (i = 0; i < WEP_KEYS; i++) {
|
for (i = 0; i < WEP_KEYS; i++) {
|
||||||
struct ieee80211_crypt_data *crypt = local->crypt[i];
|
struct lib80211_crypt_data *crypt = local->crypt_info.crypt[i];
|
||||||
if (crypt) {
|
if (crypt) {
|
||||||
if (crypt->ops)
|
if (crypt->ops)
|
||||||
crypt->ops->deinit(crypt->priv);
|
crypt->ops->deinit(crypt->priv);
|
||||||
kfree(crypt);
|
kfree(crypt);
|
||||||
local->crypt[i] = NULL;
|
local->crypt_info.crypt[i] = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/ethtool.h>
|
#include <linux/ethtool.h>
|
||||||
#include <net/ieee80211_crypt.h>
|
#include <net/lib80211.h>
|
||||||
|
|
||||||
#include "hostap_wlan.h"
|
#include "hostap_wlan.h"
|
||||||
#include "hostap.h"
|
#include "hostap.h"
|
||||||
|
@ -117,9 +117,9 @@ static int prism2_get_name(struct net_device *dev,
|
||||||
|
|
||||||
|
|
||||||
static void prism2_crypt_delayed_deinit(local_info_t *local,
|
static void prism2_crypt_delayed_deinit(local_info_t *local,
|
||||||
struct ieee80211_crypt_data **crypt)
|
struct lib80211_crypt_data **crypt)
|
||||||
{
|
{
|
||||||
struct ieee80211_crypt_data *tmp;
|
struct lib80211_crypt_data *tmp;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
tmp = *crypt;
|
tmp = *crypt;
|
||||||
|
@ -133,10 +133,10 @@ static void prism2_crypt_delayed_deinit(local_info_t *local,
|
||||||
* locking. */
|
* locking. */
|
||||||
|
|
||||||
spin_lock_irqsave(&local->lock, flags);
|
spin_lock_irqsave(&local->lock, flags);
|
||||||
list_add(&tmp->list, &local->crypt_deinit_list);
|
list_add(&tmp->list, &local->crypt_info.crypt_deinit_list);
|
||||||
if (!timer_pending(&local->crypt_deinit_timer)) {
|
if (!timer_pending(&local->crypt_info.crypt_deinit_timer)) {
|
||||||
local->crypt_deinit_timer.expires = jiffies + HZ;
|
local->crypt_info.crypt_deinit_timer.expires = jiffies + HZ;
|
||||||
add_timer(&local->crypt_deinit_timer);
|
add_timer(&local->crypt_info.crypt_deinit_timer);
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&local->lock, flags);
|
spin_unlock_irqrestore(&local->lock, flags);
|
||||||
}
|
}
|
||||||
|
@ -149,20 +149,20 @@ static int prism2_ioctl_siwencode(struct net_device *dev,
|
||||||
struct hostap_interface *iface;
|
struct hostap_interface *iface;
|
||||||
local_info_t *local;
|
local_info_t *local;
|
||||||
int i;
|
int i;
|
||||||
struct ieee80211_crypt_data **crypt;
|
struct lib80211_crypt_data **crypt;
|
||||||
|
|
||||||
iface = netdev_priv(dev);
|
iface = netdev_priv(dev);
|
||||||
local = iface->local;
|
local = iface->local;
|
||||||
|
|
||||||
i = erq->flags & IW_ENCODE_INDEX;
|
i = erq->flags & IW_ENCODE_INDEX;
|
||||||
if (i < 1 || i > 4)
|
if (i < 1 || i > 4)
|
||||||
i = local->tx_keyidx;
|
i = local->crypt_info.tx_keyidx;
|
||||||
else
|
else
|
||||||
i--;
|
i--;
|
||||||
if (i < 0 || i >= WEP_KEYS)
|
if (i < 0 || i >= WEP_KEYS)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
crypt = &local->crypt[i];
|
crypt = &local->crypt_info.crypt[i];
|
||||||
|
|
||||||
if (erq->flags & IW_ENCODE_DISABLED) {
|
if (erq->flags & IW_ENCODE_DISABLED) {
|
||||||
if (*crypt)
|
if (*crypt)
|
||||||
|
@ -177,17 +177,17 @@ static int prism2_ioctl_siwencode(struct net_device *dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*crypt == NULL) {
|
if (*crypt == NULL) {
|
||||||
struct ieee80211_crypt_data *new_crypt;
|
struct lib80211_crypt_data *new_crypt;
|
||||||
|
|
||||||
/* take WEP into use */
|
/* take WEP into use */
|
||||||
new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data),
|
new_crypt = kzalloc(sizeof(struct lib80211_crypt_data),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (new_crypt == NULL)
|
if (new_crypt == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
new_crypt->ops = ieee80211_get_crypto_ops("WEP");
|
new_crypt->ops = lib80211_get_crypto_ops("WEP");
|
||||||
if (!new_crypt->ops) {
|
if (!new_crypt->ops) {
|
||||||
request_module("ieee80211_crypt_wep");
|
request_module("lib80211_crypt_wep");
|
||||||
new_crypt->ops = ieee80211_get_crypto_ops("WEP");
|
new_crypt->ops = lib80211_get_crypto_ops("WEP");
|
||||||
}
|
}
|
||||||
if (new_crypt->ops)
|
if (new_crypt->ops)
|
||||||
new_crypt->priv = new_crypt->ops->init(i);
|
new_crypt->priv = new_crypt->ops->init(i);
|
||||||
|
@ -210,16 +210,16 @@ static int prism2_ioctl_siwencode(struct net_device *dev,
|
||||||
memset(keybuf + erq->length, 0, len - erq->length);
|
memset(keybuf + erq->length, 0, len - erq->length);
|
||||||
(*crypt)->ops->set_key(keybuf, len, NULL, (*crypt)->priv);
|
(*crypt)->ops->set_key(keybuf, len, NULL, (*crypt)->priv);
|
||||||
for (j = 0; j < WEP_KEYS; j++) {
|
for (j = 0; j < WEP_KEYS; j++) {
|
||||||
if (j != i && local->crypt[j]) {
|
if (j != i && local->crypt_info.crypt[j]) {
|
||||||
first = 0;
|
first = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (first)
|
if (first)
|
||||||
local->tx_keyidx = i;
|
local->crypt_info.tx_keyidx = i;
|
||||||
} else {
|
} else {
|
||||||
/* No key data - just set the default TX key index */
|
/* No key data - just set the default TX key index */
|
||||||
local->tx_keyidx = i;
|
local->crypt_info.tx_keyidx = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
@ -252,20 +252,20 @@ static int prism2_ioctl_giwencode(struct net_device *dev,
|
||||||
local_info_t *local;
|
local_info_t *local;
|
||||||
int i, len;
|
int i, len;
|
||||||
u16 val;
|
u16 val;
|
||||||
struct ieee80211_crypt_data *crypt;
|
struct lib80211_crypt_data *crypt;
|
||||||
|
|
||||||
iface = netdev_priv(dev);
|
iface = netdev_priv(dev);
|
||||||
local = iface->local;
|
local = iface->local;
|
||||||
|
|
||||||
i = erq->flags & IW_ENCODE_INDEX;
|
i = erq->flags & IW_ENCODE_INDEX;
|
||||||
if (i < 1 || i > 4)
|
if (i < 1 || i > 4)
|
||||||
i = local->tx_keyidx;
|
i = local->crypt_info.tx_keyidx;
|
||||||
else
|
else
|
||||||
i--;
|
i--;
|
||||||
if (i < 0 || i >= WEP_KEYS)
|
if (i < 0 || i >= WEP_KEYS)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
crypt = local->crypt[i];
|
crypt = local->crypt_info.crypt[i];
|
||||||
erq->flags = i + 1;
|
erq->flags = i + 1;
|
||||||
|
|
||||||
if (crypt == NULL || crypt->ops == NULL) {
|
if (crypt == NULL || crypt->ops == NULL) {
|
||||||
|
@ -3227,8 +3227,8 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev,
|
||||||
local_info_t *local = iface->local;
|
local_info_t *local = iface->local;
|
||||||
struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
|
struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
|
||||||
int i, ret = 0;
|
int i, ret = 0;
|
||||||
struct ieee80211_crypto_ops *ops;
|
struct lib80211_crypto_ops *ops;
|
||||||
struct ieee80211_crypt_data **crypt;
|
struct lib80211_crypt_data **crypt;
|
||||||
void *sta_ptr;
|
void *sta_ptr;
|
||||||
u8 *addr;
|
u8 *addr;
|
||||||
const char *alg, *module;
|
const char *alg, *module;
|
||||||
|
@ -3237,7 +3237,7 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev,
|
||||||
if (i > WEP_KEYS)
|
if (i > WEP_KEYS)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (i < 1 || i > WEP_KEYS)
|
if (i < 1 || i > WEP_KEYS)
|
||||||
i = local->tx_keyidx;
|
i = local->crypt_info.tx_keyidx;
|
||||||
else
|
else
|
||||||
i--;
|
i--;
|
||||||
if (i < 0 || i >= WEP_KEYS)
|
if (i < 0 || i >= WEP_KEYS)
|
||||||
|
@ -3247,7 +3247,7 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev,
|
||||||
if (addr[0] == 0xff && addr[1] == 0xff && addr[2] == 0xff &&
|
if (addr[0] == 0xff && addr[1] == 0xff && addr[2] == 0xff &&
|
||||||
addr[3] == 0xff && addr[4] == 0xff && addr[5] == 0xff) {
|
addr[3] == 0xff && addr[4] == 0xff && addr[5] == 0xff) {
|
||||||
sta_ptr = NULL;
|
sta_ptr = NULL;
|
||||||
crypt = &local->crypt[i];
|
crypt = &local->crypt_info.crypt[i];
|
||||||
} else {
|
} else {
|
||||||
if (i != 0)
|
if (i != 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -3260,7 +3260,7 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev,
|
||||||
* is emulated by using default key idx 0.
|
* is emulated by using default key idx 0.
|
||||||
*/
|
*/
|
||||||
i = 0;
|
i = 0;
|
||||||
crypt = &local->crypt[i];
|
crypt = &local->crypt_info.crypt[i];
|
||||||
} else
|
} else
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -3276,15 +3276,15 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev,
|
||||||
switch (ext->alg) {
|
switch (ext->alg) {
|
||||||
case IW_ENCODE_ALG_WEP:
|
case IW_ENCODE_ALG_WEP:
|
||||||
alg = "WEP";
|
alg = "WEP";
|
||||||
module = "ieee80211_crypt_wep";
|
module = "lib80211_crypt_wep";
|
||||||
break;
|
break;
|
||||||
case IW_ENCODE_ALG_TKIP:
|
case IW_ENCODE_ALG_TKIP:
|
||||||
alg = "TKIP";
|
alg = "TKIP";
|
||||||
module = "ieee80211_crypt_tkip";
|
module = "lib80211_crypt_tkip";
|
||||||
break;
|
break;
|
||||||
case IW_ENCODE_ALG_CCMP:
|
case IW_ENCODE_ALG_CCMP:
|
||||||
alg = "CCMP";
|
alg = "CCMP";
|
||||||
module = "ieee80211_crypt_ccmp";
|
module = "lib80211_crypt_ccmp";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printk(KERN_DEBUG "%s: unsupported algorithm %d\n",
|
printk(KERN_DEBUG "%s: unsupported algorithm %d\n",
|
||||||
|
@ -3293,10 +3293,10 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
ops = ieee80211_get_crypto_ops(alg);
|
ops = lib80211_get_crypto_ops(alg);
|
||||||
if (ops == NULL) {
|
if (ops == NULL) {
|
||||||
request_module(module);
|
request_module(module);
|
||||||
ops = ieee80211_get_crypto_ops(alg);
|
ops = lib80211_get_crypto_ops(alg);
|
||||||
}
|
}
|
||||||
if (ops == NULL) {
|
if (ops == NULL) {
|
||||||
printk(KERN_DEBUG "%s: unknown crypto alg '%s'\n",
|
printk(KERN_DEBUG "%s: unknown crypto alg '%s'\n",
|
||||||
|
@ -3315,11 +3315,11 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*crypt == NULL || (*crypt)->ops != ops) {
|
if (*crypt == NULL || (*crypt)->ops != ops) {
|
||||||
struct ieee80211_crypt_data *new_crypt;
|
struct lib80211_crypt_data *new_crypt;
|
||||||
|
|
||||||
prism2_crypt_delayed_deinit(local, crypt);
|
prism2_crypt_delayed_deinit(local, crypt);
|
||||||
|
|
||||||
new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data),
|
new_crypt = kzalloc(sizeof(struct lib80211_crypt_data),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (new_crypt == NULL) {
|
if (new_crypt == NULL) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
|
@ -3354,20 +3354,20 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev,
|
||||||
|
|
||||||
if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
|
if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
|
||||||
if (!sta_ptr)
|
if (!sta_ptr)
|
||||||
local->tx_keyidx = i;
|
local->crypt_info.tx_keyidx = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (sta_ptr == NULL && ext->key_len > 0) {
|
if (sta_ptr == NULL && ext->key_len > 0) {
|
||||||
int first = 1, j;
|
int first = 1, j;
|
||||||
for (j = 0; j < WEP_KEYS; j++) {
|
for (j = 0; j < WEP_KEYS; j++) {
|
||||||
if (j != i && local->crypt[j]) {
|
if (j != i && local->crypt_info.crypt[j]) {
|
||||||
first = 0;
|
first = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (first)
|
if (first)
|
||||||
local->tx_keyidx = i;
|
local->crypt_info.tx_keyidx = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
@ -3399,7 +3399,7 @@ static int prism2_ioctl_giwencodeext(struct net_device *dev,
|
||||||
{
|
{
|
||||||
struct hostap_interface *iface = netdev_priv(dev);
|
struct hostap_interface *iface = netdev_priv(dev);
|
||||||
local_info_t *local = iface->local;
|
local_info_t *local = iface->local;
|
||||||
struct ieee80211_crypt_data **crypt;
|
struct lib80211_crypt_data **crypt;
|
||||||
void *sta_ptr;
|
void *sta_ptr;
|
||||||
int max_key_len, i;
|
int max_key_len, i;
|
||||||
struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
|
struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
|
||||||
|
@ -3411,7 +3411,7 @@ static int prism2_ioctl_giwencodeext(struct net_device *dev,
|
||||||
|
|
||||||
i = erq->flags & IW_ENCODE_INDEX;
|
i = erq->flags & IW_ENCODE_INDEX;
|
||||||
if (i < 1 || i > WEP_KEYS)
|
if (i < 1 || i > WEP_KEYS)
|
||||||
i = local->tx_keyidx;
|
i = local->crypt_info.tx_keyidx;
|
||||||
else
|
else
|
||||||
i--;
|
i--;
|
||||||
|
|
||||||
|
@ -3419,7 +3419,7 @@ static int prism2_ioctl_giwencodeext(struct net_device *dev,
|
||||||
if (addr[0] == 0xff && addr[1] == 0xff && addr[2] == 0xff &&
|
if (addr[0] == 0xff && addr[1] == 0xff && addr[2] == 0xff &&
|
||||||
addr[3] == 0xff && addr[4] == 0xff && addr[5] == 0xff) {
|
addr[3] == 0xff && addr[4] == 0xff && addr[5] == 0xff) {
|
||||||
sta_ptr = NULL;
|
sta_ptr = NULL;
|
||||||
crypt = &local->crypt[i];
|
crypt = &local->crypt_info.crypt[i];
|
||||||
} else {
|
} else {
|
||||||
i = 0;
|
i = 0;
|
||||||
sta_ptr = ap_crypt_get_ptrs(local->ap, addr, 0, &crypt);
|
sta_ptr = ap_crypt_get_ptrs(local->ap, addr, 0, &crypt);
|
||||||
|
@ -3468,8 +3468,8 @@ static int prism2_ioctl_set_encryption(local_info_t *local,
|
||||||
int param_len)
|
int param_len)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct ieee80211_crypto_ops *ops;
|
struct lib80211_crypto_ops *ops;
|
||||||
struct ieee80211_crypt_data **crypt;
|
struct lib80211_crypt_data **crypt;
|
||||||
void *sta_ptr;
|
void *sta_ptr;
|
||||||
|
|
||||||
param->u.crypt.err = 0;
|
param->u.crypt.err = 0;
|
||||||
|
@ -3486,7 +3486,7 @@ static int prism2_ioctl_set_encryption(local_info_t *local,
|
||||||
if (param->u.crypt.idx >= WEP_KEYS)
|
if (param->u.crypt.idx >= WEP_KEYS)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
sta_ptr = NULL;
|
sta_ptr = NULL;
|
||||||
crypt = &local->crypt[param->u.crypt.idx];
|
crypt = &local->crypt_info.crypt[param->u.crypt.idx];
|
||||||
} else {
|
} else {
|
||||||
if (param->u.crypt.idx)
|
if (param->u.crypt.idx)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -3507,16 +3507,16 @@ static int prism2_ioctl_set_encryption(local_info_t *local,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
|
ops = lib80211_get_crypto_ops(param->u.crypt.alg);
|
||||||
if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) {
|
if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) {
|
||||||
request_module("ieee80211_crypt_wep");
|
request_module("lib80211_crypt_wep");
|
||||||
ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
|
ops = lib80211_get_crypto_ops(param->u.crypt.alg);
|
||||||
} else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) {
|
} else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) {
|
||||||
request_module("ieee80211_crypt_tkip");
|
request_module("lib80211_crypt_tkip");
|
||||||
ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
|
ops = lib80211_get_crypto_ops(param->u.crypt.alg);
|
||||||
} else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) {
|
} else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) {
|
||||||
request_module("ieee80211_crypt_ccmp");
|
request_module("lib80211_crypt_ccmp");
|
||||||
ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
|
ops = lib80211_get_crypto_ops(param->u.crypt.alg);
|
||||||
}
|
}
|
||||||
if (ops == NULL) {
|
if (ops == NULL) {
|
||||||
printk(KERN_DEBUG "%s: unknown crypto alg '%s'\n",
|
printk(KERN_DEBUG "%s: unknown crypto alg '%s'\n",
|
||||||
|
@ -3531,11 +3531,11 @@ static int prism2_ioctl_set_encryption(local_info_t *local,
|
||||||
local->host_decrypt = local->host_encrypt = 1;
|
local->host_decrypt = local->host_encrypt = 1;
|
||||||
|
|
||||||
if (*crypt == NULL || (*crypt)->ops != ops) {
|
if (*crypt == NULL || (*crypt)->ops != ops) {
|
||||||
struct ieee80211_crypt_data *new_crypt;
|
struct lib80211_crypt_data *new_crypt;
|
||||||
|
|
||||||
prism2_crypt_delayed_deinit(local, crypt);
|
prism2_crypt_delayed_deinit(local, crypt);
|
||||||
|
|
||||||
new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data),
|
new_crypt = kzalloc(sizeof(struct lib80211_crypt_data),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (new_crypt == NULL) {
|
if (new_crypt == NULL) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
|
@ -3568,7 +3568,7 @@ static int prism2_ioctl_set_encryption(local_info_t *local,
|
||||||
|
|
||||||
if (param->u.crypt.flags & HOSTAP_CRYPT_FLAG_SET_TX_KEY) {
|
if (param->u.crypt.flags & HOSTAP_CRYPT_FLAG_SET_TX_KEY) {
|
||||||
if (!sta_ptr)
|
if (!sta_ptr)
|
||||||
local->tx_keyidx = param->u.crypt.idx;
|
local->crypt_info.tx_keyidx = param->u.crypt.idx;
|
||||||
else if (param->u.crypt.idx) {
|
else if (param->u.crypt.idx) {
|
||||||
printk(KERN_DEBUG "%s: TX key idx setting failed\n",
|
printk(KERN_DEBUG "%s: TX key idx setting failed\n",
|
||||||
local->dev->name);
|
local->dev->name);
|
||||||
|
@ -3604,7 +3604,7 @@ static int prism2_ioctl_get_encryption(local_info_t *local,
|
||||||
struct prism2_hostapd_param *param,
|
struct prism2_hostapd_param *param,
|
||||||
int param_len)
|
int param_len)
|
||||||
{
|
{
|
||||||
struct ieee80211_crypt_data **crypt;
|
struct lib80211_crypt_data **crypt;
|
||||||
void *sta_ptr;
|
void *sta_ptr;
|
||||||
int max_key_len;
|
int max_key_len;
|
||||||
|
|
||||||
|
@ -3620,8 +3620,8 @@ static int prism2_ioctl_get_encryption(local_info_t *local,
|
||||||
param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
|
param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
|
||||||
sta_ptr = NULL;
|
sta_ptr = NULL;
|
||||||
if (param->u.crypt.idx >= WEP_KEYS)
|
if (param->u.crypt.idx >= WEP_KEYS)
|
||||||
param->u.crypt.idx = local->tx_keyidx;
|
param->u.crypt.idx = local->crypt_info.tx_keyidx;
|
||||||
crypt = &local->crypt[param->u.crypt.idx];
|
crypt = &local->crypt_info.crypt[param->u.crypt.idx];
|
||||||
} else {
|
} else {
|
||||||
param->u.crypt.idx = 0;
|
param->u.crypt.idx = 0;
|
||||||
sta_ptr = ap_crypt_get_ptrs(local->ap, param->sta_addr, 0,
|
sta_ptr = ap_crypt_get_ptrs(local->ap, param->sta_addr, 0,
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
#include <net/net_namespace.h>
|
#include <net/net_namespace.h>
|
||||||
#include <net/iw_handler.h>
|
#include <net/iw_handler.h>
|
||||||
#include <net/ieee80211.h>
|
#include <net/ieee80211.h>
|
||||||
#include <net/ieee80211_crypt.h>
|
#include <net/lib80211.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
|
|
||||||
#include "hostap_wlan.h"
|
#include "hostap_wlan.h"
|
||||||
|
@ -343,10 +343,11 @@ int hostap_set_encryption(local_info_t *local)
|
||||||
char keybuf[WEP_KEY_LEN + 1];
|
char keybuf[WEP_KEY_LEN + 1];
|
||||||
enum { NONE, WEP, OTHER } encrypt_type;
|
enum { NONE, WEP, OTHER } encrypt_type;
|
||||||
|
|
||||||
idx = local->tx_keyidx;
|
idx = local->crypt_info.tx_keyidx;
|
||||||
if (local->crypt[idx] == NULL || local->crypt[idx]->ops == NULL)
|
if (local->crypt_info.crypt[idx] == NULL ||
|
||||||
|
local->crypt_info.crypt[idx]->ops == NULL)
|
||||||
encrypt_type = NONE;
|
encrypt_type = NONE;
|
||||||
else if (strcmp(local->crypt[idx]->ops->name, "WEP") == 0)
|
else if (strcmp(local->crypt_info.crypt[idx]->ops->name, "WEP") == 0)
|
||||||
encrypt_type = WEP;
|
encrypt_type = WEP;
|
||||||
else
|
else
|
||||||
encrypt_type = OTHER;
|
encrypt_type = OTHER;
|
||||||
|
@ -394,17 +395,17 @@ int hostap_set_encryption(local_info_t *local)
|
||||||
/* 104-bit support seems to require that all the keys are set to the
|
/* 104-bit support seems to require that all the keys are set to the
|
||||||
* same keylen */
|
* same keylen */
|
||||||
keylen = 6; /* first 5 octets */
|
keylen = 6; /* first 5 octets */
|
||||||
len = local->crypt[idx]->ops->get_key(keybuf, sizeof(keybuf),
|
len = local->crypt_info.crypt[idx]->ops->get_key(keybuf, sizeof(keybuf), NULL,
|
||||||
NULL, local->crypt[idx]->priv);
|
local->crypt_info.crypt[idx]->priv);
|
||||||
if (idx >= 0 && idx < WEP_KEYS && len > 5)
|
if (idx >= 0 && idx < WEP_KEYS && len > 5)
|
||||||
keylen = WEP_KEY_LEN + 1; /* first 13 octets */
|
keylen = WEP_KEY_LEN + 1; /* first 13 octets */
|
||||||
|
|
||||||
for (i = 0; i < WEP_KEYS; i++) {
|
for (i = 0; i < WEP_KEYS; i++) {
|
||||||
memset(keybuf, 0, sizeof(keybuf));
|
memset(keybuf, 0, sizeof(keybuf));
|
||||||
if (local->crypt[i]) {
|
if (local->crypt_info.crypt[i]) {
|
||||||
(void) local->crypt[i]->ops->get_key(
|
(void) local->crypt_info.crypt[i]->ops->get_key(
|
||||||
keybuf, sizeof(keybuf),
|
keybuf, sizeof(keybuf),
|
||||||
NULL, local->crypt[i]->priv);
|
NULL, local->crypt_info.crypt[i]->priv);
|
||||||
}
|
}
|
||||||
if (local->func->set_rid(local->dev,
|
if (local->func->set_rid(local->dev,
|
||||||
HFA384X_RID_CNFDEFAULTKEY0 + i,
|
HFA384X_RID_CNFDEFAULTKEY0 + i,
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/proc_fs.h>
|
#include <linux/proc_fs.h>
|
||||||
#include <net/ieee80211_crypt.h>
|
#include <net/lib80211.h>
|
||||||
|
|
||||||
#include "hostap_wlan.h"
|
#include "hostap_wlan.h"
|
||||||
#include "hostap.h"
|
#include "hostap.h"
|
||||||
|
@ -36,9 +36,10 @@ static int prism2_debug_proc_read(char *page, char **start, off_t off,
|
||||||
p += sprintf(p, "dev_enabled=%d\n", local->dev_enabled);
|
p += sprintf(p, "dev_enabled=%d\n", local->dev_enabled);
|
||||||
p += sprintf(p, "sw_tick_stuck=%d\n", local->sw_tick_stuck);
|
p += sprintf(p, "sw_tick_stuck=%d\n", local->sw_tick_stuck);
|
||||||
for (i = 0; i < WEP_KEYS; i++) {
|
for (i = 0; i < WEP_KEYS; i++) {
|
||||||
if (local->crypt[i] && local->crypt[i]->ops) {
|
if (local->crypt_info.crypt[i] &&
|
||||||
p += sprintf(p, "crypt[%d]=%s\n",
|
local->crypt_info.crypt[i]->ops) {
|
||||||
i, local->crypt[i]->ops->name);
|
p += sprintf(p, "crypt[%d]=%s\n", i,
|
||||||
|
local->crypt_info.crypt[i]->ops->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p += sprintf(p, "pri_only=%d\n", local->pri_only);
|
p += sprintf(p, "pri_only=%d\n", local->pri_only);
|
||||||
|
@ -206,12 +207,13 @@ static int prism2_crypt_proc_read(char *page, char **start, off_t off,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
p += sprintf(p, "tx_keyidx=%d\n", local->tx_keyidx);
|
p += sprintf(p, "tx_keyidx=%d\n", local->crypt_info.tx_keyidx);
|
||||||
for (i = 0; i < WEP_KEYS; i++) {
|
for (i = 0; i < WEP_KEYS; i++) {
|
||||||
if (local->crypt[i] && local->crypt[i]->ops &&
|
if (local->crypt_info.crypt[i] &&
|
||||||
local->crypt[i]->ops->print_stats) {
|
local->crypt_info.crypt[i]->ops &&
|
||||||
p = local->crypt[i]->ops->print_stats(
|
local->crypt_info.crypt[i]->ops->print_stats) {
|
||||||
p, local->crypt[i]->priv);
|
p = local->crypt_info.crypt[i]->ops->print_stats(
|
||||||
|
p, local->crypt_info.crypt[i]->priv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
#include <net/iw_handler.h>
|
#include <net/iw_handler.h>
|
||||||
#include <net/ieee80211_radiotap.h>
|
#include <net/ieee80211_radiotap.h>
|
||||||
|
#include <net/lib80211.h>
|
||||||
|
|
||||||
#include "hostap_config.h"
|
#include "hostap_config.h"
|
||||||
#include "hostap_common.h"
|
#include "hostap_common.h"
|
||||||
|
@ -763,10 +764,7 @@ struct local_info {
|
||||||
|
|
||||||
#define WEP_KEYS 4
|
#define WEP_KEYS 4
|
||||||
#define WEP_KEY_LEN 13
|
#define WEP_KEY_LEN 13
|
||||||
struct ieee80211_crypt_data *crypt[WEP_KEYS];
|
struct lib80211_crypt_info crypt_info;
|
||||||
int tx_keyidx; /* default TX key index (crypt[tx_keyidx]) */
|
|
||||||
struct timer_list crypt_deinit_timer;
|
|
||||||
struct list_head crypt_deinit_list;
|
|
||||||
|
|
||||||
int open_wep; /* allow unencrypted frames */
|
int open_wep; /* allow unencrypted frames */
|
||||||
int host_encrypt;
|
int host_encrypt;
|
||||||
|
|
|
@ -4010,7 +4010,7 @@ static ssize_t show_internals(struct device *d, struct device_attribute *attr,
|
||||||
else
|
else
|
||||||
len += sprintf(buf + len, "not connected\n");
|
len += sprintf(buf + len, "not connected\n");
|
||||||
|
|
||||||
DUMP_VAR(ieee->crypt[priv->ieee->tx_keyidx], "p");
|
DUMP_VAR(ieee->crypt_info.crypt[priv->ieee->crypt_info.tx_keyidx], "p");
|
||||||
DUMP_VAR(status, "08lx");
|
DUMP_VAR(status, "08lx");
|
||||||
DUMP_VAR(config, "08lx");
|
DUMP_VAR(config, "08lx");
|
||||||
DUMP_VAR(capability, "08lx");
|
DUMP_VAR(capability, "08lx");
|
||||||
|
@ -5514,7 +5514,7 @@ static int ipw2100_configure_security(struct ipw2100_priv *priv, int batch_mode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ipw2100_set_key_index(priv, priv->ieee->tx_keyidx, 1);
|
ipw2100_set_key_index(priv, priv->ieee->crypt_info.tx_keyidx, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Always enable privacy so the Host can filter WEP packets if
|
/* Always enable privacy so the Host can filter WEP packets if
|
||||||
|
@ -7620,7 +7620,7 @@ static int ipw2100_wx_set_auth(struct net_device *dev,
|
||||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||||
struct ieee80211_device *ieee = priv->ieee;
|
struct ieee80211_device *ieee = priv->ieee;
|
||||||
struct iw_param *param = &wrqu->param;
|
struct iw_param *param = &wrqu->param;
|
||||||
struct ieee80211_crypt_data *crypt;
|
struct lib80211_crypt_data *crypt;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
@ -7635,7 +7635,7 @@ static int ipw2100_wx_set_auth(struct net_device *dev,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IW_AUTH_TKIP_COUNTERMEASURES:
|
case IW_AUTH_TKIP_COUNTERMEASURES:
|
||||||
crypt = priv->ieee->crypt[priv->ieee->tx_keyidx];
|
crypt = priv->ieee->crypt_info.crypt[priv->ieee->crypt_info.tx_keyidx];
|
||||||
if (!crypt || !crypt->ops->set_flags || !crypt->ops->get_flags)
|
if (!crypt || !crypt->ops->set_flags || !crypt->ops->get_flags)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -7712,7 +7712,7 @@ static int ipw2100_wx_get_auth(struct net_device *dev,
|
||||||
{
|
{
|
||||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||||
struct ieee80211_device *ieee = priv->ieee;
|
struct ieee80211_device *ieee = priv->ieee;
|
||||||
struct ieee80211_crypt_data *crypt;
|
struct lib80211_crypt_data *crypt;
|
||||||
struct iw_param *param = &wrqu->param;
|
struct iw_param *param = &wrqu->param;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
@ -7728,7 +7728,7 @@ static int ipw2100_wx_get_auth(struct net_device *dev,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IW_AUTH_TKIP_COUNTERMEASURES:
|
case IW_AUTH_TKIP_COUNTERMEASURES:
|
||||||
crypt = priv->ieee->crypt[priv->ieee->tx_keyidx];
|
crypt = priv->ieee->crypt_info.crypt[priv->ieee->crypt_info.tx_keyidx];
|
||||||
if (!crypt || !crypt->ops->get_flags) {
|
if (!crypt || !crypt->ops->get_flags) {
|
||||||
IPW_DEBUG_WARNING("Can't get TKIP countermeasures: "
|
IPW_DEBUG_WARNING("Can't get TKIP countermeasures: "
|
||||||
"crypt not set!\n");
|
"crypt not set!\n");
|
||||||
|
|
|
@ -6600,7 +6600,7 @@ static int ipw_wx_set_auth(struct net_device *dev,
|
||||||
struct ipw_priv *priv = ieee80211_priv(dev);
|
struct ipw_priv *priv = ieee80211_priv(dev);
|
||||||
struct ieee80211_device *ieee = priv->ieee;
|
struct ieee80211_device *ieee = priv->ieee;
|
||||||
struct iw_param *param = &wrqu->param;
|
struct iw_param *param = &wrqu->param;
|
||||||
struct ieee80211_crypt_data *crypt;
|
struct lib80211_crypt_data *crypt;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
@ -6622,7 +6622,7 @@ static int ipw_wx_set_auth(struct net_device *dev,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IW_AUTH_TKIP_COUNTERMEASURES:
|
case IW_AUTH_TKIP_COUNTERMEASURES:
|
||||||
crypt = priv->ieee->crypt[priv->ieee->tx_keyidx];
|
crypt = priv->ieee->crypt_info.crypt[priv->ieee->crypt_info.tx_keyidx];
|
||||||
if (!crypt || !crypt->ops->set_flags || !crypt->ops->get_flags)
|
if (!crypt || !crypt->ops->set_flags || !crypt->ops->get_flags)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -6699,7 +6699,7 @@ static int ipw_wx_get_auth(struct net_device *dev,
|
||||||
{
|
{
|
||||||
struct ipw_priv *priv = ieee80211_priv(dev);
|
struct ipw_priv *priv = ieee80211_priv(dev);
|
||||||
struct ieee80211_device *ieee = priv->ieee;
|
struct ieee80211_device *ieee = priv->ieee;
|
||||||
struct ieee80211_crypt_data *crypt;
|
struct lib80211_crypt_data *crypt;
|
||||||
struct iw_param *param = &wrqu->param;
|
struct iw_param *param = &wrqu->param;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
@ -6715,7 +6715,7 @@ static int ipw_wx_get_auth(struct net_device *dev,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IW_AUTH_TKIP_COUNTERMEASURES:
|
case IW_AUTH_TKIP_COUNTERMEASURES:
|
||||||
crypt = priv->ieee->crypt[priv->ieee->tx_keyidx];
|
crypt = priv->ieee->crypt_info.crypt[priv->ieee->crypt_info.tx_keyidx];
|
||||||
if (!crypt || !crypt->ops->get_flags)
|
if (!crypt || !crypt->ops->get_flags)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -10251,8 +10251,8 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb,
|
||||||
case SEC_LEVEL_1:
|
case SEC_LEVEL_1:
|
||||||
tfd->u.data.tfd.tfd_24.mchdr.frame_ctl |=
|
tfd->u.data.tfd.tfd_24.mchdr.frame_ctl |=
|
||||||
cpu_to_le16(IEEE80211_FCTL_PROTECTED);
|
cpu_to_le16(IEEE80211_FCTL_PROTECTED);
|
||||||
tfd->u.data.key_index = priv->ieee->tx_keyidx;
|
tfd->u.data.key_index = priv->ieee->crypt_info.tx_keyidx;
|
||||||
if (priv->ieee->sec.key_sizes[priv->ieee->tx_keyidx] <=
|
if (priv->ieee->sec.key_sizes[priv->ieee->crypt_info.tx_keyidx] <=
|
||||||
40)
|
40)
|
||||||
tfd->u.data.key_index |= DCT_WEP_KEY_64Bit;
|
tfd->u.data.key_index |= DCT_WEP_KEY_64Bit;
|
||||||
else
|
else
|
||||||
|
|
|
@ -30,6 +30,8 @@
|
||||||
#include <linux/wireless.h>
|
#include <linux/wireless.h>
|
||||||
#include <linux/ieee80211.h>
|
#include <linux/ieee80211.h>
|
||||||
|
|
||||||
|
#include <net/lib80211.h>
|
||||||
|
|
||||||
#define IEEE80211_VERSION "git-1.1.13"
|
#define IEEE80211_VERSION "git-1.1.13"
|
||||||
|
|
||||||
#define IEEE80211_DATA_LEN 2304
|
#define IEEE80211_DATA_LEN 2304
|
||||||
|
@ -355,8 +357,6 @@ struct ieee80211_stats {
|
||||||
|
|
||||||
struct ieee80211_device;
|
struct ieee80211_device;
|
||||||
|
|
||||||
#include "ieee80211_crypt.h"
|
|
||||||
|
|
||||||
#define SEC_KEY_1 (1<<0)
|
#define SEC_KEY_1 (1<<0)
|
||||||
#define SEC_KEY_2 (1<<1)
|
#define SEC_KEY_2 (1<<1)
|
||||||
#define SEC_KEY_3 (1<<2)
|
#define SEC_KEY_3 (1<<2)
|
||||||
|
@ -937,11 +937,7 @@ struct ieee80211_device {
|
||||||
size_t wpa_ie_len;
|
size_t wpa_ie_len;
|
||||||
u8 *wpa_ie;
|
u8 *wpa_ie;
|
||||||
|
|
||||||
struct list_head crypt_deinit_list;
|
struct lib80211_crypt_info crypt_info;
|
||||||
struct ieee80211_crypt_data *crypt[WEP_KEYS];
|
|
||||||
int tx_keyidx; /* default TX key index (crypt[tx_keyidx]) */
|
|
||||||
struct timer_list crypt_deinit_timer;
|
|
||||||
int crypt_quiesced;
|
|
||||||
|
|
||||||
int bcrx_sta_key; /* use individual keys to override default keys even
|
int bcrx_sta_key; /* use individual keys to override default keys even
|
||||||
* with RX of broad/multicast frames */
|
* with RX of broad/multicast frames */
|
||||||
|
|
|
@ -1,108 +0,0 @@
|
||||||
/*
|
|
||||||
* Original code based on Host AP (software wireless LAN access point) driver
|
|
||||||
* for Intersil Prism2/2.5/3.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
|
|
||||||
* <j@w1.fi>
|
|
||||||
* Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi>
|
|
||||||
*
|
|
||||||
* Adaption to a generic IEEE 802.11 stack by James Ketrenos
|
|
||||||
* <jketreno@linux.intel.com>
|
|
||||||
*
|
|
||||||
* Copyright (c) 2004, Intel Corporation
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
* published by the Free Software Foundation. See README and COPYING for
|
|
||||||
* more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file defines the interface to the ieee80211 crypto module.
|
|
||||||
*/
|
|
||||||
#ifndef IEEE80211_CRYPT_H
|
|
||||||
#define IEEE80211_CRYPT_H
|
|
||||||
|
|
||||||
#include <linux/types.h>
|
|
||||||
#include <linux/list.h>
|
|
||||||
#include <net/ieee80211.h>
|
|
||||||
#include <asm/atomic.h>
|
|
||||||
|
|
||||||
enum {
|
|
||||||
IEEE80211_CRYPTO_TKIP_COUNTERMEASURES = (1 << 0),
|
|
||||||
};
|
|
||||||
|
|
||||||
struct sk_buff;
|
|
||||||
struct module;
|
|
||||||
|
|
||||||
struct ieee80211_crypto_ops {
|
|
||||||
const char *name;
|
|
||||||
struct list_head list;
|
|
||||||
|
|
||||||
/* init new crypto context (e.g., allocate private data space,
|
|
||||||
* select IV, etc.); returns NULL on failure or pointer to allocated
|
|
||||||
* private data on success */
|
|
||||||
void *(*init) (int keyidx);
|
|
||||||
|
|
||||||
/* deinitialize crypto context and free allocated private data */
|
|
||||||
void (*deinit) (void *priv);
|
|
||||||
|
|
||||||
int (*build_iv) (struct sk_buff * skb, int hdr_len,
|
|
||||||
u8 *key, int keylen, void *priv);
|
|
||||||
|
|
||||||
/* encrypt/decrypt return < 0 on error or >= 0 on success. The return
|
|
||||||
* value from decrypt_mpdu is passed as the keyidx value for
|
|
||||||
* decrypt_msdu. skb must have enough head and tail room for the
|
|
||||||
* encryption; if not, error will be returned; these functions are
|
|
||||||
* called for all MPDUs (i.e., fragments).
|
|
||||||
*/
|
|
||||||
int (*encrypt_mpdu) (struct sk_buff * skb, int hdr_len, void *priv);
|
|
||||||
int (*decrypt_mpdu) (struct sk_buff * skb, int hdr_len, void *priv);
|
|
||||||
|
|
||||||
/* These functions are called for full MSDUs, i.e. full frames.
|
|
||||||
* These can be NULL if full MSDU operations are not needed. */
|
|
||||||
int (*encrypt_msdu) (struct sk_buff * skb, int hdr_len, void *priv);
|
|
||||||
int (*decrypt_msdu) (struct sk_buff * skb, int keyidx, int hdr_len,
|
|
||||||
void *priv);
|
|
||||||
|
|
||||||
int (*set_key) (void *key, int len, u8 * seq, void *priv);
|
|
||||||
int (*get_key) (void *key, int len, u8 * seq, void *priv);
|
|
||||||
|
|
||||||
/* procfs handler for printing out key information and possible
|
|
||||||
* statistics */
|
|
||||||
char *(*print_stats) (char *p, void *priv);
|
|
||||||
|
|
||||||
/* Crypto specific flag get/set for configuration settings */
|
|
||||||
unsigned long (*get_flags) (void *priv);
|
|
||||||
unsigned long (*set_flags) (unsigned long flags, void *priv);
|
|
||||||
|
|
||||||
/* maximum number of bytes added by encryption; encrypt buf is
|
|
||||||
* allocated with extra_prefix_len bytes, copy of in_buf, and
|
|
||||||
* extra_postfix_len; encrypt need not use all this space, but
|
|
||||||
* the result must start at the beginning of the buffer and correct
|
|
||||||
* length must be returned */
|
|
||||||
int extra_mpdu_prefix_len, extra_mpdu_postfix_len;
|
|
||||||
int extra_msdu_prefix_len, extra_msdu_postfix_len;
|
|
||||||
|
|
||||||
struct module *owner;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ieee80211_crypt_data {
|
|
||||||
struct list_head list; /* delayed deletion list */
|
|
||||||
struct ieee80211_crypto_ops *ops;
|
|
||||||
void *priv;
|
|
||||||
atomic_t refcnt;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ieee80211_device;
|
|
||||||
|
|
||||||
int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops);
|
|
||||||
int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops);
|
|
||||||
struct ieee80211_crypto_ops *ieee80211_get_crypto_ops(const char *name);
|
|
||||||
void ieee80211_crypt_deinit_entries(struct ieee80211_device *, int);
|
|
||||||
void ieee80211_crypt_deinit_handler(unsigned long);
|
|
||||||
void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
|
|
||||||
struct ieee80211_crypt_data **crypt);
|
|
||||||
void ieee80211_crypt_quiescing(struct ieee80211_device *ieee);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -3,11 +3,32 @@
|
||||||
*
|
*
|
||||||
* Copyright (c) 2008, John W. Linville <linville@tuxdriver.com>
|
* Copyright (c) 2008, John W. Linville <linville@tuxdriver.com>
|
||||||
*
|
*
|
||||||
|
* Some bits copied from old ieee80211 component, w/ original copyright
|
||||||
|
* notices below:
|
||||||
|
*
|
||||||
|
* Original code based on Host AP (software wireless LAN access point) driver
|
||||||
|
* for Intersil Prism2/2.5/3.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
|
||||||
|
* <j@w1.fi>
|
||||||
|
* Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi>
|
||||||
|
*
|
||||||
|
* Adaption to a generic IEEE 802.11 stack by James Ketrenos
|
||||||
|
* <jketreno@linux.intel.com>
|
||||||
|
*
|
||||||
|
* Copyright (c) 2004, Intel Corporation
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef LIB80211_H
|
#ifndef LIB80211_H
|
||||||
#define LIB80211_H
|
#define LIB80211_H
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/list.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <asm/atomic.h>
|
||||||
|
#include <linux/if.h>
|
||||||
|
#include <linux/skbuff.h>
|
||||||
#include <linux/ieee80211.h>
|
#include <linux/ieee80211.h>
|
||||||
|
|
||||||
/* print_ssid() is intended to be used in debug (and possibly error)
|
/* print_ssid() is intended to be used in debug (and possibly error)
|
||||||
|
@ -15,4 +36,91 @@
|
||||||
const char *print_ssid(char *buf, const char *ssid, u8 ssid_len);
|
const char *print_ssid(char *buf, const char *ssid, u8 ssid_len);
|
||||||
#define DECLARE_SSID_BUF(var) char var[IEEE80211_MAX_SSID_LEN * 4 + 1] __maybe_unused
|
#define DECLARE_SSID_BUF(var) char var[IEEE80211_MAX_SSID_LEN * 4 + 1] __maybe_unused
|
||||||
|
|
||||||
|
#define NUM_WEP_KEYS 4
|
||||||
|
|
||||||
|
enum {
|
||||||
|
IEEE80211_CRYPTO_TKIP_COUNTERMEASURES = (1 << 0),
|
||||||
|
};
|
||||||
|
|
||||||
|
struct lib80211_crypto_ops {
|
||||||
|
const char *name;
|
||||||
|
struct list_head list;
|
||||||
|
|
||||||
|
/* init new crypto context (e.g., allocate private data space,
|
||||||
|
* select IV, etc.); returns NULL on failure or pointer to allocated
|
||||||
|
* private data on success */
|
||||||
|
void *(*init) (int keyidx);
|
||||||
|
|
||||||
|
/* deinitialize crypto context and free allocated private data */
|
||||||
|
void (*deinit) (void *priv);
|
||||||
|
|
||||||
|
int (*build_iv) (struct sk_buff * skb, int hdr_len,
|
||||||
|
u8 *key, int keylen, void *priv);
|
||||||
|
|
||||||
|
/* encrypt/decrypt return < 0 on error or >= 0 on success. The return
|
||||||
|
* value from decrypt_mpdu is passed as the keyidx value for
|
||||||
|
* decrypt_msdu. skb must have enough head and tail room for the
|
||||||
|
* encryption; if not, error will be returned; these functions are
|
||||||
|
* called for all MPDUs (i.e., fragments).
|
||||||
|
*/
|
||||||
|
int (*encrypt_mpdu) (struct sk_buff * skb, int hdr_len, void *priv);
|
||||||
|
int (*decrypt_mpdu) (struct sk_buff * skb, int hdr_len, void *priv);
|
||||||
|
|
||||||
|
/* These functions are called for full MSDUs, i.e. full frames.
|
||||||
|
* These can be NULL if full MSDU operations are not needed. */
|
||||||
|
int (*encrypt_msdu) (struct sk_buff * skb, int hdr_len, void *priv);
|
||||||
|
int (*decrypt_msdu) (struct sk_buff * skb, int keyidx, int hdr_len,
|
||||||
|
void *priv);
|
||||||
|
|
||||||
|
int (*set_key) (void *key, int len, u8 * seq, void *priv);
|
||||||
|
int (*get_key) (void *key, int len, u8 * seq, void *priv);
|
||||||
|
|
||||||
|
/* procfs handler for printing out key information and possible
|
||||||
|
* statistics */
|
||||||
|
char *(*print_stats) (char *p, void *priv);
|
||||||
|
|
||||||
|
/* Crypto specific flag get/set for configuration settings */
|
||||||
|
unsigned long (*get_flags) (void *priv);
|
||||||
|
unsigned long (*set_flags) (unsigned long flags, void *priv);
|
||||||
|
|
||||||
|
/* maximum number of bytes added by encryption; encrypt buf is
|
||||||
|
* allocated with extra_prefix_len bytes, copy of in_buf, and
|
||||||
|
* extra_postfix_len; encrypt need not use all this space, but
|
||||||
|
* the result must start at the beginning of the buffer and correct
|
||||||
|
* length must be returned */
|
||||||
|
int extra_mpdu_prefix_len, extra_mpdu_postfix_len;
|
||||||
|
int extra_msdu_prefix_len, extra_msdu_postfix_len;
|
||||||
|
|
||||||
|
struct module *owner;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct lib80211_crypt_data {
|
||||||
|
struct list_head list; /* delayed deletion list */
|
||||||
|
struct lib80211_crypto_ops *ops;
|
||||||
|
void *priv;
|
||||||
|
atomic_t refcnt;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct lib80211_crypt_info {
|
||||||
|
char *name;
|
||||||
|
/* Most clients will already have a lock,
|
||||||
|
so just point to that. */
|
||||||
|
spinlock_t *lock;
|
||||||
|
|
||||||
|
struct lib80211_crypt_data *crypt[NUM_WEP_KEYS];
|
||||||
|
int tx_keyidx; /* default TX key index (crypt[tx_keyidx]) */
|
||||||
|
struct list_head crypt_deinit_list;
|
||||||
|
struct timer_list crypt_deinit_timer;
|
||||||
|
int crypt_quiesced;
|
||||||
|
};
|
||||||
|
|
||||||
|
int lib80211_register_crypto_ops(struct lib80211_crypto_ops *ops);
|
||||||
|
int lib80211_unregister_crypto_ops(struct lib80211_crypto_ops *ops);
|
||||||
|
struct lib80211_crypto_ops *lib80211_get_crypto_ops(const char *name);
|
||||||
|
void lib80211_crypt_deinit_entries(struct lib80211_crypt_info *, int);
|
||||||
|
void lib80211_crypt_deinit_handler(unsigned long);
|
||||||
|
void lib80211_crypt_delayed_deinit(struct lib80211_crypt_info *info,
|
||||||
|
struct lib80211_crypt_data **crypt);
|
||||||
|
void lib80211_crypt_quiescing(struct lib80211_crypt_info *info);
|
||||||
|
|
||||||
#endif /* LIB80211_H */
|
#endif /* LIB80211_H */
|
||||||
|
|
|
@ -8,10 +8,10 @@ config IEEE80211
|
||||||
select CRYPTO_MICHAEL_MIC
|
select CRYPTO_MICHAEL_MIC
|
||||||
select CRYPTO_ECB
|
select CRYPTO_ECB
|
||||||
select CRC32
|
select CRC32
|
||||||
select IEEE80211_CRYPT_WEP
|
|
||||||
select IEEE80211_CRYPT_TKIP
|
|
||||||
select IEEE80211_CRYPT_CCMP
|
|
||||||
select LIB80211
|
select LIB80211
|
||||||
|
select LIB80211_CRYPT_WEP
|
||||||
|
select LIB80211_CRYPT_TKIP
|
||||||
|
select LIB80211_CRYPT_CCMP
|
||||||
---help---
|
---help---
|
||||||
This option enables the hardware independent IEEE 802.11
|
This option enables the hardware independent IEEE 802.11
|
||||||
networking stack. This component is deprecated in favor of the
|
networking stack. This component is deprecated in favor of the
|
||||||
|
@ -39,12 +39,3 @@ config IEEE80211_DEBUG
|
||||||
|
|
||||||
If you are not trying to debug or develop the ieee80211
|
If you are not trying to debug or develop the ieee80211
|
||||||
subsystem, you most likely want to say N here.
|
subsystem, you most likely want to say N here.
|
||||||
|
|
||||||
config IEEE80211_CRYPT_WEP
|
|
||||||
tristate
|
|
||||||
|
|
||||||
config IEEE80211_CRYPT_CCMP
|
|
||||||
tristate
|
|
||||||
|
|
||||||
config IEEE80211_CRYPT_TKIP
|
|
||||||
tristate
|
|
||||||
|
|
|
@ -1,8 +1,4 @@
|
||||||
obj-$(CONFIG_IEEE80211) += ieee80211.o
|
obj-$(CONFIG_IEEE80211) += ieee80211.o
|
||||||
obj-$(CONFIG_IEEE80211) += ieee80211_crypt.o
|
|
||||||
obj-$(CONFIG_IEEE80211_CRYPT_WEP) += ieee80211_crypt_wep.o
|
|
||||||
obj-$(CONFIG_IEEE80211_CRYPT_CCMP) += ieee80211_crypt_ccmp.o
|
|
||||||
obj-$(CONFIG_IEEE80211_CRYPT_TKIP) += ieee80211_crypt_tkip.o
|
|
||||||
ieee80211-objs := \
|
ieee80211-objs := \
|
||||||
ieee80211_module.o \
|
ieee80211_module.o \
|
||||||
ieee80211_tx.o \
|
ieee80211_tx.o \
|
||||||
|
|
|
@ -1,206 +0,0 @@
|
||||||
/*
|
|
||||||
* Host AP crypto routines
|
|
||||||
*
|
|
||||||
* Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi>
|
|
||||||
* Portions Copyright (C) 2004, Intel Corporation <jketreno@linux.intel.com>
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
* published by the Free Software Foundation. See README and COPYING for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/errno.h>
|
|
||||||
#include <linux/module.h>
|
|
||||||
#include <linux/init.h>
|
|
||||||
#include <linux/slab.h>
|
|
||||||
#include <linux/string.h>
|
|
||||||
#include <net/ieee80211.h>
|
|
||||||
|
|
||||||
MODULE_AUTHOR("Jouni Malinen");
|
|
||||||
MODULE_DESCRIPTION("HostAP crypto");
|
|
||||||
MODULE_LICENSE("GPL");
|
|
||||||
|
|
||||||
struct ieee80211_crypto_alg {
|
|
||||||
struct list_head list;
|
|
||||||
struct ieee80211_crypto_ops *ops;
|
|
||||||
};
|
|
||||||
|
|
||||||
static LIST_HEAD(ieee80211_crypto_algs);
|
|
||||||
static DEFINE_SPINLOCK(ieee80211_crypto_lock);
|
|
||||||
|
|
||||||
void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee, int force)
|
|
||||||
{
|
|
||||||
struct ieee80211_crypt_data *entry, *next;
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&ieee->lock, flags);
|
|
||||||
list_for_each_entry_safe(entry, next, &ieee->crypt_deinit_list, list) {
|
|
||||||
if (atomic_read(&entry->refcnt) != 0 && !force)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
list_del(&entry->list);
|
|
||||||
|
|
||||||
if (entry->ops) {
|
|
||||||
entry->ops->deinit(entry->priv);
|
|
||||||
module_put(entry->ops->owner);
|
|
||||||
}
|
|
||||||
kfree(entry);
|
|
||||||
}
|
|
||||||
spin_unlock_irqrestore(&ieee->lock, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* After this, crypt_deinit_list won't accept new members */
|
|
||||||
void ieee80211_crypt_quiescing(struct ieee80211_device *ieee)
|
|
||||||
{
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&ieee->lock, flags);
|
|
||||||
ieee->crypt_quiesced = 1;
|
|
||||||
spin_unlock_irqrestore(&ieee->lock, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ieee80211_crypt_deinit_handler(unsigned long data)
|
|
||||||
{
|
|
||||||
struct ieee80211_device *ieee = (struct ieee80211_device *)data;
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
ieee80211_crypt_deinit_entries(ieee, 0);
|
|
||||||
|
|
||||||
spin_lock_irqsave(&ieee->lock, flags);
|
|
||||||
if (!list_empty(&ieee->crypt_deinit_list) && !ieee->crypt_quiesced) {
|
|
||||||
printk(KERN_DEBUG "%s: entries remaining in delayed crypt "
|
|
||||||
"deletion list\n", ieee->dev->name);
|
|
||||||
ieee->crypt_deinit_timer.expires = jiffies + HZ;
|
|
||||||
add_timer(&ieee->crypt_deinit_timer);
|
|
||||||
}
|
|
||||||
spin_unlock_irqrestore(&ieee->lock, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
|
|
||||||
struct ieee80211_crypt_data **crypt)
|
|
||||||
{
|
|
||||||
struct ieee80211_crypt_data *tmp;
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
if (*crypt == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
tmp = *crypt;
|
|
||||||
*crypt = NULL;
|
|
||||||
|
|
||||||
/* must not run ops->deinit() while there may be pending encrypt or
|
|
||||||
* decrypt operations. Use a list of delayed deinits to avoid needing
|
|
||||||
* locking. */
|
|
||||||
|
|
||||||
spin_lock_irqsave(&ieee->lock, flags);
|
|
||||||
if (!ieee->crypt_quiesced) {
|
|
||||||
list_add(&tmp->list, &ieee->crypt_deinit_list);
|
|
||||||
if (!timer_pending(&ieee->crypt_deinit_timer)) {
|
|
||||||
ieee->crypt_deinit_timer.expires = jiffies + HZ;
|
|
||||||
add_timer(&ieee->crypt_deinit_timer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
spin_unlock_irqrestore(&ieee->lock, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops)
|
|
||||||
{
|
|
||||||
unsigned long flags;
|
|
||||||
struct ieee80211_crypto_alg *alg;
|
|
||||||
|
|
||||||
alg = kzalloc(sizeof(*alg), GFP_KERNEL);
|
|
||||||
if (alg == NULL)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
alg->ops = ops;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&ieee80211_crypto_lock, flags);
|
|
||||||
list_add(&alg->list, &ieee80211_crypto_algs);
|
|
||||||
spin_unlock_irqrestore(&ieee80211_crypto_lock, flags);
|
|
||||||
|
|
||||||
printk(KERN_DEBUG "ieee80211_crypt: registered algorithm '%s'\n",
|
|
||||||
ops->name);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops)
|
|
||||||
{
|
|
||||||
struct ieee80211_crypto_alg *alg;
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&ieee80211_crypto_lock, flags);
|
|
||||||
list_for_each_entry(alg, &ieee80211_crypto_algs, list) {
|
|
||||||
if (alg->ops == ops)
|
|
||||||
goto found;
|
|
||||||
}
|
|
||||||
spin_unlock_irqrestore(&ieee80211_crypto_lock, flags);
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
found:
|
|
||||||
printk(KERN_DEBUG "ieee80211_crypt: unregistered algorithm "
|
|
||||||
"'%s'\n", ops->name);
|
|
||||||
list_del(&alg->list);
|
|
||||||
spin_unlock_irqrestore(&ieee80211_crypto_lock, flags);
|
|
||||||
kfree(alg);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ieee80211_crypto_ops *ieee80211_get_crypto_ops(const char *name)
|
|
||||||
{
|
|
||||||
struct ieee80211_crypto_alg *alg;
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&ieee80211_crypto_lock, flags);
|
|
||||||
list_for_each_entry(alg, &ieee80211_crypto_algs, list) {
|
|
||||||
if (strcmp(alg->ops->name, name) == 0)
|
|
||||||
goto found;
|
|
||||||
}
|
|
||||||
spin_unlock_irqrestore(&ieee80211_crypto_lock, flags);
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
found:
|
|
||||||
spin_unlock_irqrestore(&ieee80211_crypto_lock, flags);
|
|
||||||
return alg->ops;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *ieee80211_crypt_null_init(int keyidx)
|
|
||||||
{
|
|
||||||
return (void *)1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ieee80211_crypt_null_deinit(void *priv)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct ieee80211_crypto_ops ieee80211_crypt_null = {
|
|
||||||
.name = "NULL",
|
|
||||||
.init = ieee80211_crypt_null_init,
|
|
||||||
.deinit = ieee80211_crypt_null_deinit,
|
|
||||||
.owner = THIS_MODULE,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int __init ieee80211_crypto_init(void)
|
|
||||||
{
|
|
||||||
return ieee80211_register_crypto_ops(&ieee80211_crypt_null);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __exit ieee80211_crypto_deinit(void)
|
|
||||||
{
|
|
||||||
ieee80211_unregister_crypto_ops(&ieee80211_crypt_null);
|
|
||||||
BUG_ON(!list_empty(&ieee80211_crypto_algs));
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT_SYMBOL(ieee80211_crypt_deinit_entries);
|
|
||||||
EXPORT_SYMBOL(ieee80211_crypt_deinit_handler);
|
|
||||||
EXPORT_SYMBOL(ieee80211_crypt_delayed_deinit);
|
|
||||||
EXPORT_SYMBOL(ieee80211_crypt_quiescing);
|
|
||||||
|
|
||||||
EXPORT_SYMBOL(ieee80211_register_crypto_ops);
|
|
||||||
EXPORT_SYMBOL(ieee80211_unregister_crypto_ops);
|
|
||||||
EXPORT_SYMBOL(ieee80211_get_crypto_ops);
|
|
||||||
|
|
||||||
module_init(ieee80211_crypto_init);
|
|
||||||
module_exit(ieee80211_crypto_deinit);
|
|
|
@ -180,13 +180,16 @@ struct net_device *alloc_ieee80211(int sizeof_priv)
|
||||||
ieee->host_open_frag = 1;
|
ieee->host_open_frag = 1;
|
||||||
ieee->ieee802_1x = 1; /* Default to supporting 802.1x */
|
ieee->ieee802_1x = 1; /* Default to supporting 802.1x */
|
||||||
|
|
||||||
INIT_LIST_HEAD(&ieee->crypt_deinit_list);
|
|
||||||
setup_timer(&ieee->crypt_deinit_timer, ieee80211_crypt_deinit_handler,
|
|
||||||
(unsigned long)ieee);
|
|
||||||
ieee->crypt_quiesced = 0;
|
|
||||||
|
|
||||||
spin_lock_init(&ieee->lock);
|
spin_lock_init(&ieee->lock);
|
||||||
|
|
||||||
|
ieee->crypt_info.name = dev->name;
|
||||||
|
ieee->crypt_info.lock = &ieee->lock;
|
||||||
|
INIT_LIST_HEAD(&ieee->crypt_info.crypt_deinit_list);
|
||||||
|
setup_timer(&ieee->crypt_info.crypt_deinit_timer,
|
||||||
|
lib80211_crypt_deinit_handler,
|
||||||
|
(unsigned long)&ieee->crypt_info);
|
||||||
|
ieee->crypt_info.crypt_quiesced = 0;
|
||||||
|
|
||||||
ieee->wpa_enabled = 0;
|
ieee->wpa_enabled = 0;
|
||||||
ieee->drop_unencrypted = 0;
|
ieee->drop_unencrypted = 0;
|
||||||
ieee->privacy_invoked = 0;
|
ieee->privacy_invoked = 0;
|
||||||
|
@ -205,19 +208,19 @@ void free_ieee80211(struct net_device *dev)
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
ieee80211_crypt_quiescing(ieee);
|
lib80211_crypt_quiescing(&ieee->crypt_info);
|
||||||
del_timer_sync(&ieee->crypt_deinit_timer);
|
del_timer_sync(&ieee->crypt_info.crypt_deinit_timer);
|
||||||
ieee80211_crypt_deinit_entries(ieee, 1);
|
lib80211_crypt_deinit_entries(&ieee->crypt_info, 1);
|
||||||
|
|
||||||
for (i = 0; i < WEP_KEYS; i++) {
|
for (i = 0; i < WEP_KEYS; i++) {
|
||||||
struct ieee80211_crypt_data *crypt = ieee->crypt[i];
|
struct lib80211_crypt_data *crypt = ieee->crypt_info.crypt[i];
|
||||||
if (crypt) {
|
if (crypt) {
|
||||||
if (crypt->ops) {
|
if (crypt->ops) {
|
||||||
crypt->ops->deinit(crypt->priv);
|
crypt->ops->deinit(crypt->priv);
|
||||||
module_put(crypt->ops->owner);
|
module_put(crypt->ops->owner);
|
||||||
}
|
}
|
||||||
kfree(crypt);
|
kfree(crypt);
|
||||||
ieee->crypt[i] = NULL;
|
ieee->crypt_info.crypt[i] = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -268,7 +268,7 @@ static int ieee80211_is_eapol_frame(struct ieee80211_device *ieee,
|
||||||
/* Called only as a tasklet (software IRQ), by ieee80211_rx */
|
/* Called only as a tasklet (software IRQ), by ieee80211_rx */
|
||||||
static int
|
static int
|
||||||
ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb,
|
ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb,
|
||||||
struct ieee80211_crypt_data *crypt)
|
struct lib80211_crypt_data *crypt)
|
||||||
{
|
{
|
||||||
struct ieee80211_hdr_3addr *hdr;
|
struct ieee80211_hdr_3addr *hdr;
|
||||||
int res, hdrlen;
|
int res, hdrlen;
|
||||||
|
@ -300,7 +300,7 @@ ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb,
|
||||||
static int
|
static int
|
||||||
ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device *ieee,
|
ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device *ieee,
|
||||||
struct sk_buff *skb, int keyidx,
|
struct sk_buff *skb, int keyidx,
|
||||||
struct ieee80211_crypt_data *crypt)
|
struct lib80211_crypt_data *crypt)
|
||||||
{
|
{
|
||||||
struct ieee80211_hdr_3addr *hdr;
|
struct ieee80211_hdr_3addr *hdr;
|
||||||
int res, hdrlen;
|
int res, hdrlen;
|
||||||
|
@ -348,7 +348,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
|
||||||
#endif
|
#endif
|
||||||
u8 dst[ETH_ALEN];
|
u8 dst[ETH_ALEN];
|
||||||
u8 src[ETH_ALEN];
|
u8 src[ETH_ALEN];
|
||||||
struct ieee80211_crypt_data *crypt = NULL;
|
struct lib80211_crypt_data *crypt = NULL;
|
||||||
int keyidx = 0;
|
int keyidx = 0;
|
||||||
int can_be_decrypted = 0;
|
int can_be_decrypted = 0;
|
||||||
|
|
||||||
|
@ -431,7 +431,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
|
||||||
* is only allowed 2-bits of storage, no value of keyidx can
|
* is only allowed 2-bits of storage, no value of keyidx can
|
||||||
* be provided via above code that would result in keyidx
|
* be provided via above code that would result in keyidx
|
||||||
* being out of range */
|
* being out of range */
|
||||||
crypt = ieee->crypt[keyidx];
|
crypt = ieee->crypt_info.crypt[keyidx];
|
||||||
|
|
||||||
#ifdef NOT_YET
|
#ifdef NOT_YET
|
||||||
sta = NULL;
|
sta = NULL;
|
||||||
|
|
|
@ -152,7 +152,8 @@ static int ieee80211_copy_snap(u8 * data, __be16 h_proto)
|
||||||
static int ieee80211_encrypt_fragment(struct ieee80211_device *ieee,
|
static int ieee80211_encrypt_fragment(struct ieee80211_device *ieee,
|
||||||
struct sk_buff *frag, int hdr_len)
|
struct sk_buff *frag, int hdr_len)
|
||||||
{
|
{
|
||||||
struct ieee80211_crypt_data *crypt = ieee->crypt[ieee->tx_keyidx];
|
struct lib80211_crypt_data *crypt =
|
||||||
|
ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx];
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
if (crypt == NULL)
|
if (crypt == NULL)
|
||||||
|
@ -270,7 +271,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||||
.qos_ctl = 0
|
.qos_ctl = 0
|
||||||
};
|
};
|
||||||
u8 dest[ETH_ALEN], src[ETH_ALEN];
|
u8 dest[ETH_ALEN], src[ETH_ALEN];
|
||||||
struct ieee80211_crypt_data *crypt;
|
struct lib80211_crypt_data *crypt;
|
||||||
int priority = skb->priority;
|
int priority = skb->priority;
|
||||||
int snapped = 0;
|
int snapped = 0;
|
||||||
|
|
||||||
|
@ -294,7 +295,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||||
|
|
||||||
ether_type = ((struct ethhdr *)skb->data)->h_proto;
|
ether_type = ((struct ethhdr *)skb->data)->h_proto;
|
||||||
|
|
||||||
crypt = ieee->crypt[ieee->tx_keyidx];
|
crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx];
|
||||||
|
|
||||||
encrypt = !(ether_type == htons(ETH_P_PAE) && ieee->ieee802_1x) &&
|
encrypt = !(ether_type == htons(ETH_P_PAE) && ieee->ieee802_1x) &&
|
||||||
ieee->sec.encrypt;
|
ieee->sec.encrypt;
|
||||||
|
|
|
@ -307,7 +307,7 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
|
||||||
.flags = 0
|
.flags = 0
|
||||||
};
|
};
|
||||||
int i, key, key_provided, len;
|
int i, key, key_provided, len;
|
||||||
struct ieee80211_crypt_data **crypt;
|
struct lib80211_crypt_data **crypt;
|
||||||
int host_crypto = ieee->host_encrypt || ieee->host_decrypt || ieee->host_build_iv;
|
int host_crypto = ieee->host_encrypt || ieee->host_decrypt || ieee->host_build_iv;
|
||||||
DECLARE_SSID_BUF(ssid);
|
DECLARE_SSID_BUF(ssid);
|
||||||
|
|
||||||
|
@ -321,30 +321,30 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
|
||||||
key_provided = 1;
|
key_provided = 1;
|
||||||
} else {
|
} else {
|
||||||
key_provided = 0;
|
key_provided = 0;
|
||||||
key = ieee->tx_keyidx;
|
key = ieee->crypt_info.tx_keyidx;
|
||||||
}
|
}
|
||||||
|
|
||||||
IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
|
IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
|
||||||
"provided" : "default");
|
"provided" : "default");
|
||||||
|
|
||||||
crypt = &ieee->crypt[key];
|
crypt = &ieee->crypt_info.crypt[key];
|
||||||
|
|
||||||
if (erq->flags & IW_ENCODE_DISABLED) {
|
if (erq->flags & IW_ENCODE_DISABLED) {
|
||||||
if (key_provided && *crypt) {
|
if (key_provided && *crypt) {
|
||||||
IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
|
IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
|
||||||
key);
|
key);
|
||||||
ieee80211_crypt_delayed_deinit(ieee, crypt);
|
lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
|
||||||
} else
|
} else
|
||||||
IEEE80211_DEBUG_WX("Disabling encryption.\n");
|
IEEE80211_DEBUG_WX("Disabling encryption.\n");
|
||||||
|
|
||||||
/* Check all the keys to see if any are still configured,
|
/* Check all the keys to see if any are still configured,
|
||||||
* and if no key index was provided, de-init them all */
|
* and if no key index was provided, de-init them all */
|
||||||
for (i = 0; i < WEP_KEYS; i++) {
|
for (i = 0; i < WEP_KEYS; i++) {
|
||||||
if (ieee->crypt[i] != NULL) {
|
if (ieee->crypt_info.crypt[i] != NULL) {
|
||||||
if (key_provided)
|
if (key_provided)
|
||||||
break;
|
break;
|
||||||
ieee80211_crypt_delayed_deinit(ieee,
|
lib80211_crypt_delayed_deinit(&ieee->crypt_info,
|
||||||
&ieee->crypt[i]);
|
&ieee->crypt_info.crypt[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,21 +366,21 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
|
||||||
strcmp((*crypt)->ops->name, "WEP") != 0) {
|
strcmp((*crypt)->ops->name, "WEP") != 0) {
|
||||||
/* changing to use WEP; deinit previously used algorithm
|
/* changing to use WEP; deinit previously used algorithm
|
||||||
* on this key */
|
* on this key */
|
||||||
ieee80211_crypt_delayed_deinit(ieee, crypt);
|
lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*crypt == NULL && host_crypto) {
|
if (*crypt == NULL && host_crypto) {
|
||||||
struct ieee80211_crypt_data *new_crypt;
|
struct lib80211_crypt_data *new_crypt;
|
||||||
|
|
||||||
/* take WEP into use */
|
/* take WEP into use */
|
||||||
new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data),
|
new_crypt = kzalloc(sizeof(struct lib80211_crypt_data),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (new_crypt == NULL)
|
if (new_crypt == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
new_crypt->ops = ieee80211_get_crypto_ops("WEP");
|
new_crypt->ops = lib80211_get_crypto_ops("WEP");
|
||||||
if (!new_crypt->ops) {
|
if (!new_crypt->ops) {
|
||||||
request_module("ieee80211_crypt_wep");
|
request_module("lib80211_crypt_wep");
|
||||||
new_crypt->ops = ieee80211_get_crypto_ops("WEP");
|
new_crypt->ops = lib80211_get_crypto_ops("WEP");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
|
if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
|
||||||
|
@ -391,7 +391,7 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
|
||||||
new_crypt = NULL;
|
new_crypt = NULL;
|
||||||
|
|
||||||
printk(KERN_WARNING "%s: could not initialize WEP: "
|
printk(KERN_WARNING "%s: could not initialize WEP: "
|
||||||
"load module ieee80211_crypt_wep\n", dev->name);
|
"load module lib80211_crypt_wep\n", dev->name);
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
*crypt = new_crypt;
|
*crypt = new_crypt;
|
||||||
|
@ -440,7 +440,7 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
|
||||||
if (key_provided) {
|
if (key_provided) {
|
||||||
IEEE80211_DEBUG_WX("Setting key %d to default Tx "
|
IEEE80211_DEBUG_WX("Setting key %d to default Tx "
|
||||||
"key.\n", key);
|
"key.\n", key);
|
||||||
ieee->tx_keyidx = key;
|
ieee->crypt_info.tx_keyidx = key;
|
||||||
sec.active_key = key;
|
sec.active_key = key;
|
||||||
sec.flags |= SEC_ACTIVE_KEY;
|
sec.flags |= SEC_ACTIVE_KEY;
|
||||||
}
|
}
|
||||||
|
@ -485,7 +485,7 @@ int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
|
||||||
{
|
{
|
||||||
struct iw_point *erq = &(wrqu->encoding);
|
struct iw_point *erq = &(wrqu->encoding);
|
||||||
int len, key;
|
int len, key;
|
||||||
struct ieee80211_crypt_data *crypt;
|
struct lib80211_crypt_data *crypt;
|
||||||
struct ieee80211_security *sec = &ieee->sec;
|
struct ieee80211_security *sec = &ieee->sec;
|
||||||
|
|
||||||
IEEE80211_DEBUG_WX("GET_ENCODE\n");
|
IEEE80211_DEBUG_WX("GET_ENCODE\n");
|
||||||
|
@ -496,9 +496,9 @@ int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
key--;
|
key--;
|
||||||
} else
|
} else
|
||||||
key = ieee->tx_keyidx;
|
key = ieee->crypt_info.tx_keyidx;
|
||||||
|
|
||||||
crypt = ieee->crypt[key];
|
crypt = ieee->crypt_info.crypt[key];
|
||||||
erq->flags = key + 1;
|
erq->flags = key + 1;
|
||||||
|
|
||||||
if (!sec->enabled) {
|
if (!sec->enabled) {
|
||||||
|
@ -531,8 +531,8 @@ int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee,
|
||||||
int i, idx, ret = 0;
|
int i, idx, ret = 0;
|
||||||
int group_key = 0;
|
int group_key = 0;
|
||||||
const char *alg, *module;
|
const char *alg, *module;
|
||||||
struct ieee80211_crypto_ops *ops;
|
struct lib80211_crypto_ops *ops;
|
||||||
struct ieee80211_crypt_data **crypt;
|
struct lib80211_crypt_data **crypt;
|
||||||
|
|
||||||
struct ieee80211_security sec = {
|
struct ieee80211_security sec = {
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
|
@ -544,17 +544,17 @@ int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
idx--;
|
idx--;
|
||||||
} else
|
} else
|
||||||
idx = ieee->tx_keyidx;
|
idx = ieee->crypt_info.tx_keyidx;
|
||||||
|
|
||||||
if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
|
if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
|
||||||
crypt = &ieee->crypt[idx];
|
crypt = &ieee->crypt_info.crypt[idx];
|
||||||
group_key = 1;
|
group_key = 1;
|
||||||
} else {
|
} else {
|
||||||
/* some Cisco APs use idx>0 for unicast in dynamic WEP */
|
/* some Cisco APs use idx>0 for unicast in dynamic WEP */
|
||||||
if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
|
if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (ieee->iw_mode == IW_MODE_INFRA)
|
if (ieee->iw_mode == IW_MODE_INFRA)
|
||||||
crypt = &ieee->crypt[idx];
|
crypt = &ieee->crypt_info.crypt[idx];
|
||||||
else
|
else
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -563,10 +563,10 @@ int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee,
|
||||||
if ((encoding->flags & IW_ENCODE_DISABLED) ||
|
if ((encoding->flags & IW_ENCODE_DISABLED) ||
|
||||||
ext->alg == IW_ENCODE_ALG_NONE) {
|
ext->alg == IW_ENCODE_ALG_NONE) {
|
||||||
if (*crypt)
|
if (*crypt)
|
||||||
ieee80211_crypt_delayed_deinit(ieee, crypt);
|
lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
|
||||||
|
|
||||||
for (i = 0; i < WEP_KEYS; i++)
|
for (i = 0; i < WEP_KEYS; i++)
|
||||||
if (ieee->crypt[i] != NULL)
|
if (ieee->crypt_info.crypt[i] != NULL)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (i == WEP_KEYS) {
|
if (i == WEP_KEYS) {
|
||||||
|
@ -589,15 +589,15 @@ int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee,
|
||||||
switch (ext->alg) {
|
switch (ext->alg) {
|
||||||
case IW_ENCODE_ALG_WEP:
|
case IW_ENCODE_ALG_WEP:
|
||||||
alg = "WEP";
|
alg = "WEP";
|
||||||
module = "ieee80211_crypt_wep";
|
module = "lib80211_crypt_wep";
|
||||||
break;
|
break;
|
||||||
case IW_ENCODE_ALG_TKIP:
|
case IW_ENCODE_ALG_TKIP:
|
||||||
alg = "TKIP";
|
alg = "TKIP";
|
||||||
module = "ieee80211_crypt_tkip";
|
module = "lib80211_crypt_tkip";
|
||||||
break;
|
break;
|
||||||
case IW_ENCODE_ALG_CCMP:
|
case IW_ENCODE_ALG_CCMP:
|
||||||
alg = "CCMP";
|
alg = "CCMP";
|
||||||
module = "ieee80211_crypt_ccmp";
|
module = "lib80211_crypt_ccmp";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
|
IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
|
||||||
|
@ -606,10 +606,10 @@ int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
ops = ieee80211_get_crypto_ops(alg);
|
ops = lib80211_get_crypto_ops(alg);
|
||||||
if (ops == NULL) {
|
if (ops == NULL) {
|
||||||
request_module(module);
|
request_module(module);
|
||||||
ops = ieee80211_get_crypto_ops(alg);
|
ops = lib80211_get_crypto_ops(alg);
|
||||||
}
|
}
|
||||||
if (ops == NULL) {
|
if (ops == NULL) {
|
||||||
IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
|
IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
|
||||||
|
@ -619,9 +619,9 @@ int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*crypt == NULL || (*crypt)->ops != ops) {
|
if (*crypt == NULL || (*crypt)->ops != ops) {
|
||||||
struct ieee80211_crypt_data *new_crypt;
|
struct lib80211_crypt_data *new_crypt;
|
||||||
|
|
||||||
ieee80211_crypt_delayed_deinit(ieee, crypt);
|
lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
|
||||||
|
|
||||||
new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
|
new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
|
||||||
if (new_crypt == NULL) {
|
if (new_crypt == NULL) {
|
||||||
|
@ -649,7 +649,7 @@ int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee,
|
||||||
|
|
||||||
skip_host_crypt:
|
skip_host_crypt:
|
||||||
if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
|
if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
|
||||||
ieee->tx_keyidx = idx;
|
ieee->crypt_info.tx_keyidx = idx;
|
||||||
sec.active_key = idx;
|
sec.active_key = idx;
|
||||||
sec.flags |= SEC_ACTIVE_KEY;
|
sec.flags |= SEC_ACTIVE_KEY;
|
||||||
}
|
}
|
||||||
|
@ -715,7 +715,7 @@ int ieee80211_wx_get_encodeext(struct ieee80211_device *ieee,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
idx--;
|
idx--;
|
||||||
} else
|
} else
|
||||||
idx = ieee->tx_keyidx;
|
idx = ieee->crypt_info.tx_keyidx;
|
||||||
|
|
||||||
if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) &&
|
if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) &&
|
||||||
ext->alg != IW_ENCODE_ALG_WEP)
|
ext->alg != IW_ENCODE_ALG_WEP)
|
||||||
|
|
|
@ -82,3 +82,12 @@ config LIB80211
|
||||||
|
|
||||||
Drivers should select this themselves if needed. Say Y if
|
Drivers should select this themselves if needed. Say Y if
|
||||||
you want this built into your kernel.
|
you want this built into your kernel.
|
||||||
|
|
||||||
|
config LIB80211_CRYPT_WEP
|
||||||
|
tristate
|
||||||
|
|
||||||
|
config LIB80211_CRYPT_CCMP
|
||||||
|
tristate
|
||||||
|
|
||||||
|
config LIB80211_CRYPT_TKIP
|
||||||
|
tristate
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
obj-$(CONFIG_WIRELESS_EXT) += wext.o
|
obj-$(CONFIG_WIRELESS_EXT) += wext.o
|
||||||
obj-$(CONFIG_CFG80211) += cfg80211.o
|
obj-$(CONFIG_CFG80211) += cfg80211.o
|
||||||
obj-$(CONFIG_LIB80211) += lib80211.o
|
obj-$(CONFIG_LIB80211) += lib80211.o
|
||||||
|
obj-$(CONFIG_LIB80211_CRYPT_WEP) += lib80211_crypt_wep.o
|
||||||
|
obj-$(CONFIG_LIB80211_CRYPT_CCMP) += lib80211_crypt_ccmp.o
|
||||||
|
obj-$(CONFIG_LIB80211_CRYPT_TKIP) += lib80211_crypt_tkip.o
|
||||||
|
|
||||||
cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o
|
cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o
|
||||||
cfg80211-$(CONFIG_NL80211) += nl80211.o
|
cfg80211-$(CONFIG_NL80211) += nl80211.o
|
||||||
|
|
|
@ -3,11 +3,23 @@
|
||||||
*
|
*
|
||||||
* Copyright(c) 2008 John W. Linville <linville@tuxdriver.com>
|
* Copyright(c) 2008 John W. Linville <linville@tuxdriver.com>
|
||||||
*
|
*
|
||||||
|
* Portions copied from old ieee80211 component, w/ original copyright
|
||||||
|
* notices below:
|
||||||
|
*
|
||||||
|
* Host AP crypto routines
|
||||||
|
*
|
||||||
|
* Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi>
|
||||||
|
* Portions Copyright (C) 2004, Intel Corporation <jketreno@linux.intel.com>
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/ctype.h>
|
#include <linux/ctype.h>
|
||||||
#include <linux/ieee80211.h>
|
#include <linux/ieee80211.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
|
||||||
#include <net/lib80211.h>
|
#include <net/lib80211.h>
|
||||||
|
|
||||||
|
@ -19,6 +31,14 @@ MODULE_DESCRIPTION(DRV_DESCRIPTION);
|
||||||
MODULE_AUTHOR("John W. Linville <linville@tuxdriver.com>");
|
MODULE_AUTHOR("John W. Linville <linville@tuxdriver.com>");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
|
struct lib80211_crypto_alg {
|
||||||
|
struct list_head list;
|
||||||
|
struct lib80211_crypto_ops *ops;
|
||||||
|
};
|
||||||
|
|
||||||
|
static LIST_HEAD(lib80211_crypto_algs);
|
||||||
|
static DEFINE_SPINLOCK(lib80211_crypto_lock);
|
||||||
|
|
||||||
const char *print_ssid(char *buf, const char *ssid, u8 ssid_len)
|
const char *print_ssid(char *buf, const char *ssid, u8 ssid_len)
|
||||||
{
|
{
|
||||||
const char *s = ssid;
|
const char *s = ssid;
|
||||||
|
@ -51,15 +71,176 @@ const char *print_ssid(char *buf, const char *ssid, u8 ssid_len)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(print_ssid);
|
EXPORT_SYMBOL(print_ssid);
|
||||||
|
|
||||||
static int __init ieee80211_init(void)
|
void lib80211_crypt_deinit_entries(struct lib80211_crypt_info *info, int force)
|
||||||
{
|
{
|
||||||
printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION "\n");
|
struct lib80211_crypt_data *entry, *next;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(info->lock, flags);
|
||||||
|
list_for_each_entry_safe(entry, next, &info->crypt_deinit_list, list) {
|
||||||
|
if (atomic_read(&entry->refcnt) != 0 && !force)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
list_del(&entry->list);
|
||||||
|
|
||||||
|
if (entry->ops) {
|
||||||
|
entry->ops->deinit(entry->priv);
|
||||||
|
module_put(entry->ops->owner);
|
||||||
|
}
|
||||||
|
kfree(entry);
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(info->lock, flags);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(lib80211_crypt_deinit_entries);
|
||||||
|
|
||||||
|
/* After this, crypt_deinit_list won't accept new members */
|
||||||
|
void lib80211_crypt_quiescing(struct lib80211_crypt_info *info)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(info->lock, flags);
|
||||||
|
info->crypt_quiesced = 1;
|
||||||
|
spin_unlock_irqrestore(info->lock, flags);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(lib80211_crypt_quiescing);
|
||||||
|
|
||||||
|
void lib80211_crypt_deinit_handler(unsigned long data)
|
||||||
|
{
|
||||||
|
struct lib80211_crypt_info *info = (struct lib80211_crypt_info *)data;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
lib80211_crypt_deinit_entries(info, 0);
|
||||||
|
|
||||||
|
spin_lock_irqsave(info->lock, flags);
|
||||||
|
if (!list_empty(&info->crypt_deinit_list) && !info->crypt_quiesced) {
|
||||||
|
printk(KERN_DEBUG "%s: entries remaining in delayed crypt "
|
||||||
|
"deletion list\n", info->name);
|
||||||
|
info->crypt_deinit_timer.expires = jiffies + HZ;
|
||||||
|
add_timer(&info->crypt_deinit_timer);
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(info->lock, flags);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(lib80211_crypt_deinit_handler);
|
||||||
|
|
||||||
|
void lib80211_crypt_delayed_deinit(struct lib80211_crypt_info *info,
|
||||||
|
struct lib80211_crypt_data **crypt)
|
||||||
|
{
|
||||||
|
struct lib80211_crypt_data *tmp;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
if (*crypt == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
tmp = *crypt;
|
||||||
|
*crypt = NULL;
|
||||||
|
|
||||||
|
/* must not run ops->deinit() while there may be pending encrypt or
|
||||||
|
* decrypt operations. Use a list of delayed deinits to avoid needing
|
||||||
|
* locking. */
|
||||||
|
|
||||||
|
spin_lock_irqsave(info->lock, flags);
|
||||||
|
if (!info->crypt_quiesced) {
|
||||||
|
list_add(&tmp->list, &info->crypt_deinit_list);
|
||||||
|
if (!timer_pending(&info->crypt_deinit_timer)) {
|
||||||
|
info->crypt_deinit_timer.expires = jiffies + HZ;
|
||||||
|
add_timer(&info->crypt_deinit_timer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(info->lock, flags);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(lib80211_crypt_delayed_deinit);
|
||||||
|
|
||||||
|
int lib80211_register_crypto_ops(struct lib80211_crypto_ops *ops)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
struct lib80211_crypto_alg *alg;
|
||||||
|
|
||||||
|
alg = kzalloc(sizeof(*alg), GFP_KERNEL);
|
||||||
|
if (alg == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
alg->ops = ops;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&lib80211_crypto_lock, flags);
|
||||||
|
list_add(&alg->list, &lib80211_crypto_algs);
|
||||||
|
spin_unlock_irqrestore(&lib80211_crypto_lock, flags);
|
||||||
|
|
||||||
|
printk(KERN_DEBUG "lib80211_crypt: registered algorithm '%s'\n",
|
||||||
|
ops->name);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(lib80211_register_crypto_ops);
|
||||||
|
|
||||||
static void __exit ieee80211_exit(void)
|
int lib80211_unregister_crypto_ops(struct lib80211_crypto_ops *ops)
|
||||||
|
{
|
||||||
|
struct lib80211_crypto_alg *alg;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&lib80211_crypto_lock, flags);
|
||||||
|
list_for_each_entry(alg, &lib80211_crypto_algs, list) {
|
||||||
|
if (alg->ops == ops)
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&lib80211_crypto_lock, flags);
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
found:
|
||||||
|
printk(KERN_DEBUG "lib80211_crypt: unregistered algorithm "
|
||||||
|
"'%s'\n", ops->name);
|
||||||
|
list_del(&alg->list);
|
||||||
|
spin_unlock_irqrestore(&lib80211_crypto_lock, flags);
|
||||||
|
kfree(alg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(lib80211_unregister_crypto_ops);
|
||||||
|
|
||||||
|
struct lib80211_crypto_ops *lib80211_get_crypto_ops(const char *name)
|
||||||
|
{
|
||||||
|
struct lib80211_crypto_alg *alg;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&lib80211_crypto_lock, flags);
|
||||||
|
list_for_each_entry(alg, &lib80211_crypto_algs, list) {
|
||||||
|
if (strcmp(alg->ops->name, name) == 0)
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&lib80211_crypto_lock, flags);
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
found:
|
||||||
|
spin_unlock_irqrestore(&lib80211_crypto_lock, flags);
|
||||||
|
return alg->ops;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(lib80211_get_crypto_ops);
|
||||||
|
|
||||||
|
static void *lib80211_crypt_null_init(int keyidx)
|
||||||
|
{
|
||||||
|
return (void *)1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lib80211_crypt_null_deinit(void *priv)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init(ieee80211_init);
|
static struct lib80211_crypto_ops lib80211_crypt_null = {
|
||||||
module_exit(ieee80211_exit);
|
.name = "NULL",
|
||||||
|
.init = lib80211_crypt_null_init,
|
||||||
|
.deinit = lib80211_crypt_null_deinit,
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init lib80211_init(void)
|
||||||
|
{
|
||||||
|
printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION "\n");
|
||||||
|
return lib80211_register_crypto_ops(&lib80211_crypt_null);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit lib80211_exit(void)
|
||||||
|
{
|
||||||
|
lib80211_unregister_crypto_ops(&lib80211_crypt_null);
|
||||||
|
BUG_ON(!list_empty(&lib80211_crypto_algs));
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(lib80211_init);
|
||||||
|
module_exit(lib80211_exit);
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* Host AP crypt: host-based CCMP encryption implementation for Host AP driver
|
* lib80211 crypt: host-based CCMP encryption implementation for lib80211
|
||||||
*
|
*
|
||||||
* Copyright (c) 2003-2004, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2003-2004, Jouni Malinen <j@w1.fi>
|
||||||
|
* Copyright (c) 2008, John W. Linville <linville@tuxdriver.com>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
@ -22,10 +23,12 @@
|
||||||
#include <asm/string.h>
|
#include <asm/string.h>
|
||||||
#include <linux/wireless.h>
|
#include <linux/wireless.h>
|
||||||
|
|
||||||
#include <net/ieee80211.h>
|
#include <linux/ieee80211.h>
|
||||||
|
|
||||||
#include <linux/crypto.h>
|
#include <linux/crypto.h>
|
||||||
|
|
||||||
|
#include <net/lib80211.h>
|
||||||
|
|
||||||
MODULE_AUTHOR("Jouni Malinen");
|
MODULE_AUTHOR("Jouni Malinen");
|
||||||
MODULE_DESCRIPTION("Host AP crypt: CCMP");
|
MODULE_DESCRIPTION("Host AP crypt: CCMP");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
@ -36,7 +39,7 @@ MODULE_LICENSE("GPL");
|
||||||
#define CCMP_TK_LEN 16
|
#define CCMP_TK_LEN 16
|
||||||
#define CCMP_PN_LEN 6
|
#define CCMP_PN_LEN 6
|
||||||
|
|
||||||
struct ieee80211_ccmp_data {
|
struct lib80211_ccmp_data {
|
||||||
u8 key[CCMP_TK_LEN];
|
u8 key[CCMP_TK_LEN];
|
||||||
int key_set;
|
int key_set;
|
||||||
|
|
||||||
|
@ -57,15 +60,15 @@ struct ieee80211_ccmp_data {
|
||||||
u8 rx_b0[AES_BLOCK_LEN], rx_b[AES_BLOCK_LEN], rx_a[AES_BLOCK_LEN];
|
u8 rx_b0[AES_BLOCK_LEN], rx_b[AES_BLOCK_LEN], rx_a[AES_BLOCK_LEN];
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline void ieee80211_ccmp_aes_encrypt(struct crypto_cipher *tfm,
|
static inline void lib80211_ccmp_aes_encrypt(struct crypto_cipher *tfm,
|
||||||
const u8 pt[16], u8 ct[16])
|
const u8 pt[16], u8 ct[16])
|
||||||
{
|
{
|
||||||
crypto_cipher_encrypt_one(tfm, ct, pt);
|
crypto_cipher_encrypt_one(tfm, ct, pt);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *ieee80211_ccmp_init(int key_idx)
|
static void *lib80211_ccmp_init(int key_idx)
|
||||||
{
|
{
|
||||||
struct ieee80211_ccmp_data *priv;
|
struct lib80211_ccmp_data *priv;
|
||||||
|
|
||||||
priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
|
priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
|
||||||
if (priv == NULL)
|
if (priv == NULL)
|
||||||
|
@ -74,7 +77,7 @@ static void *ieee80211_ccmp_init(int key_idx)
|
||||||
|
|
||||||
priv->tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
|
priv->tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
|
||||||
if (IS_ERR(priv->tfm)) {
|
if (IS_ERR(priv->tfm)) {
|
||||||
printk(KERN_DEBUG "ieee80211_crypt_ccmp: could not allocate "
|
printk(KERN_DEBUG "lib80211_crypt_ccmp: could not allocate "
|
||||||
"crypto API aes\n");
|
"crypto API aes\n");
|
||||||
priv->tfm = NULL;
|
priv->tfm = NULL;
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -92,9 +95,9 @@ static void *ieee80211_ccmp_init(int key_idx)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ieee80211_ccmp_deinit(void *priv)
|
static void lib80211_ccmp_deinit(void *priv)
|
||||||
{
|
{
|
||||||
struct ieee80211_ccmp_data *_priv = priv;
|
struct lib80211_ccmp_data *_priv = priv;
|
||||||
if (_priv && _priv->tfm)
|
if (_priv && _priv->tfm)
|
||||||
crypto_free_cipher(_priv->tfm);
|
crypto_free_cipher(_priv->tfm);
|
||||||
kfree(priv);
|
kfree(priv);
|
||||||
|
@ -108,20 +111,17 @@ static inline void xor_block(u8 * b, u8 * a, size_t len)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ccmp_init_blocks(struct crypto_cipher *tfm,
|
static void ccmp_init_blocks(struct crypto_cipher *tfm,
|
||||||
struct ieee80211_hdr_4addr *hdr,
|
struct ieee80211_hdr *hdr,
|
||||||
u8 * pn, size_t dlen, u8 * b0, u8 * auth, u8 * s0)
|
u8 * pn, size_t dlen, u8 * b0, u8 * auth, u8 * s0)
|
||||||
{
|
{
|
||||||
u8 *pos, qc = 0;
|
u8 *pos, qc = 0;
|
||||||
size_t aad_len;
|
size_t aad_len;
|
||||||
u16 fc;
|
|
||||||
int a4_included, qc_included;
|
int a4_included, qc_included;
|
||||||
u8 aad[2 * AES_BLOCK_LEN];
|
u8 aad[2 * AES_BLOCK_LEN];
|
||||||
|
|
||||||
fc = le16_to_cpu(hdr->frame_ctl);
|
a4_included = ieee80211_has_a4(hdr->frame_control);
|
||||||
a4_included = ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
|
qc_included = ieee80211_is_data_qos(hdr->frame_control);
|
||||||
(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS));
|
|
||||||
qc_included = ((WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) &&
|
|
||||||
(WLAN_FC_GET_STYPE(fc) & IEEE80211_STYPE_QOS_DATA));
|
|
||||||
aad_len = 22;
|
aad_len = 22;
|
||||||
if (a4_included)
|
if (a4_included)
|
||||||
aad_len += 6;
|
aad_len += 6;
|
||||||
|
@ -158,7 +158,7 @@ static void ccmp_init_blocks(struct crypto_cipher *tfm,
|
||||||
aad[2] = pos[0] & 0x8f;
|
aad[2] = pos[0] & 0x8f;
|
||||||
aad[3] = pos[1] & 0xc7;
|
aad[3] = pos[1] & 0xc7;
|
||||||
memcpy(aad + 4, hdr->addr1, 3 * ETH_ALEN);
|
memcpy(aad + 4, hdr->addr1, 3 * ETH_ALEN);
|
||||||
pos = (u8 *) & hdr->seq_ctl;
|
pos = (u8 *) & hdr->seq_ctrl;
|
||||||
aad[22] = pos[0] & 0x0f;
|
aad[22] = pos[0] & 0x0f;
|
||||||
aad[23] = 0; /* all bits masked */
|
aad[23] = 0; /* all bits masked */
|
||||||
memset(aad + 24, 0, 8);
|
memset(aad + 24, 0, 8);
|
||||||
|
@ -170,20 +170,20 @@ static void ccmp_init_blocks(struct crypto_cipher *tfm,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Start with the first block and AAD */
|
/* Start with the first block and AAD */
|
||||||
ieee80211_ccmp_aes_encrypt(tfm, b0, auth);
|
lib80211_ccmp_aes_encrypt(tfm, b0, auth);
|
||||||
xor_block(auth, aad, AES_BLOCK_LEN);
|
xor_block(auth, aad, AES_BLOCK_LEN);
|
||||||
ieee80211_ccmp_aes_encrypt(tfm, auth, auth);
|
lib80211_ccmp_aes_encrypt(tfm, auth, auth);
|
||||||
xor_block(auth, &aad[AES_BLOCK_LEN], AES_BLOCK_LEN);
|
xor_block(auth, &aad[AES_BLOCK_LEN], AES_BLOCK_LEN);
|
||||||
ieee80211_ccmp_aes_encrypt(tfm, auth, auth);
|
lib80211_ccmp_aes_encrypt(tfm, auth, auth);
|
||||||
b0[0] &= 0x07;
|
b0[0] &= 0x07;
|
||||||
b0[14] = b0[15] = 0;
|
b0[14] = b0[15] = 0;
|
||||||
ieee80211_ccmp_aes_encrypt(tfm, b0, s0);
|
lib80211_ccmp_aes_encrypt(tfm, b0, s0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ieee80211_ccmp_hdr(struct sk_buff *skb, int hdr_len,
|
static int lib80211_ccmp_hdr(struct sk_buff *skb, int hdr_len,
|
||||||
u8 *aeskey, int keylen, void *priv)
|
u8 *aeskey, int keylen, void *priv)
|
||||||
{
|
{
|
||||||
struct ieee80211_ccmp_data *key = priv;
|
struct lib80211_ccmp_data *key = priv;
|
||||||
int i;
|
int i;
|
||||||
u8 *pos;
|
u8 *pos;
|
||||||
|
|
||||||
|
@ -217,12 +217,12 @@ static int ieee80211_ccmp_hdr(struct sk_buff *skb, int hdr_len,
|
||||||
return CCMP_HDR_LEN;
|
return CCMP_HDR_LEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
|
static int lib80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
|
||||||
{
|
{
|
||||||
struct ieee80211_ccmp_data *key = priv;
|
struct lib80211_ccmp_data *key = priv;
|
||||||
int data_len, i, blocks, last, len;
|
int data_len, i, blocks, last, len;
|
||||||
u8 *pos, *mic;
|
u8 *pos, *mic;
|
||||||
struct ieee80211_hdr_4addr *hdr;
|
struct ieee80211_hdr *hdr;
|
||||||
u8 *b0 = key->tx_b0;
|
u8 *b0 = key->tx_b0;
|
||||||
u8 *b = key->tx_b;
|
u8 *b = key->tx_b;
|
||||||
u8 *e = key->tx_e;
|
u8 *e = key->tx_e;
|
||||||
|
@ -232,13 +232,13 @@ static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
data_len = skb->len - hdr_len;
|
data_len = skb->len - hdr_len;
|
||||||
len = ieee80211_ccmp_hdr(skb, hdr_len, NULL, 0, priv);
|
len = lib80211_ccmp_hdr(skb, hdr_len, NULL, 0, priv);
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
pos = skb->data + hdr_len + CCMP_HDR_LEN;
|
pos = skb->data + hdr_len + CCMP_HDR_LEN;
|
||||||
mic = skb_put(skb, CCMP_MIC_LEN);
|
mic = skb_put(skb, CCMP_MIC_LEN);
|
||||||
hdr = (struct ieee80211_hdr_4addr *)skb->data;
|
hdr = (struct ieee80211_hdr *)skb->data;
|
||||||
ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0);
|
ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0);
|
||||||
|
|
||||||
blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN);
|
blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN);
|
||||||
|
@ -248,11 +248,11 @@ static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
|
||||||
len = (i == blocks && last) ? last : AES_BLOCK_LEN;
|
len = (i == blocks && last) ? last : AES_BLOCK_LEN;
|
||||||
/* Authentication */
|
/* Authentication */
|
||||||
xor_block(b, pos, len);
|
xor_block(b, pos, len);
|
||||||
ieee80211_ccmp_aes_encrypt(key->tfm, b, b);
|
lib80211_ccmp_aes_encrypt(key->tfm, b, b);
|
||||||
/* Encryption, with counter */
|
/* Encryption, with counter */
|
||||||
b0[14] = (i >> 8) & 0xff;
|
b0[14] = (i >> 8) & 0xff;
|
||||||
b0[15] = i & 0xff;
|
b0[15] = i & 0xff;
|
||||||
ieee80211_ccmp_aes_encrypt(key->tfm, b0, e);
|
lib80211_ccmp_aes_encrypt(key->tfm, b0, e);
|
||||||
xor_block(pos, e, len);
|
xor_block(pos, e, len);
|
||||||
pos += len;
|
pos += len;
|
||||||
}
|
}
|
||||||
|
@ -284,11 +284,11 @@ static inline int ccmp_replay_check(u8 *pn_n, u8 *pn_o)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
|
static int lib80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
|
||||||
{
|
{
|
||||||
struct ieee80211_ccmp_data *key = priv;
|
struct lib80211_ccmp_data *key = priv;
|
||||||
u8 keyidx, *pos;
|
u8 keyidx, *pos;
|
||||||
struct ieee80211_hdr_4addr *hdr;
|
struct ieee80211_hdr *hdr;
|
||||||
u8 *b0 = key->rx_b0;
|
u8 *b0 = key->rx_b0;
|
||||||
u8 *b = key->rx_b;
|
u8 *b = key->rx_b;
|
||||||
u8 *a = key->rx_a;
|
u8 *a = key->rx_a;
|
||||||
|
@ -302,7 +302,7 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
hdr = (struct ieee80211_hdr_4addr *)skb->data;
|
hdr = (struct ieee80211_hdr *)skb->data;
|
||||||
pos = skb->data + hdr_len;
|
pos = skb->data + hdr_len;
|
||||||
keyidx = pos[3];
|
keyidx = pos[3];
|
||||||
if (!(keyidx & (1 << 5))) {
|
if (!(keyidx & (1 << 5))) {
|
||||||
|
@ -337,8 +337,8 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
|
||||||
pos += 8;
|
pos += 8;
|
||||||
|
|
||||||
if (ccmp_replay_check(pn, key->rx_pn)) {
|
if (ccmp_replay_check(pn, key->rx_pn)) {
|
||||||
if (ieee80211_ratelimit_debug(IEEE80211_DL_DROP)) {
|
if (net_ratelimit()) {
|
||||||
IEEE80211_DEBUG_DROP("CCMP: replay detected: STA=%pM "
|
printk(KERN_DEBUG "CCMP: replay detected: STA=%pM "
|
||||||
"previous PN %02x%02x%02x%02x%02x%02x "
|
"previous PN %02x%02x%02x%02x%02x%02x "
|
||||||
"received PN %02x%02x%02x%02x%02x%02x\n",
|
"received PN %02x%02x%02x%02x%02x%02x\n",
|
||||||
hdr->addr2,
|
hdr->addr2,
|
||||||
|
@ -361,11 +361,11 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
|
||||||
/* Decrypt, with counter */
|
/* Decrypt, with counter */
|
||||||
b0[14] = (i >> 8) & 0xff;
|
b0[14] = (i >> 8) & 0xff;
|
||||||
b0[15] = i & 0xff;
|
b0[15] = i & 0xff;
|
||||||
ieee80211_ccmp_aes_encrypt(key->tfm, b0, b);
|
lib80211_ccmp_aes_encrypt(key->tfm, b0, b);
|
||||||
xor_block(pos, b, len);
|
xor_block(pos, b, len);
|
||||||
/* Authentication */
|
/* Authentication */
|
||||||
xor_block(a, pos, len);
|
xor_block(a, pos, len);
|
||||||
ieee80211_ccmp_aes_encrypt(key->tfm, a, a);
|
lib80211_ccmp_aes_encrypt(key->tfm, a, a);
|
||||||
pos += len;
|
pos += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,9 +388,9 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
|
||||||
return keyidx;
|
return keyidx;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ieee80211_ccmp_set_key(void *key, int len, u8 * seq, void *priv)
|
static int lib80211_ccmp_set_key(void *key, int len, u8 * seq, void *priv)
|
||||||
{
|
{
|
||||||
struct ieee80211_ccmp_data *data = priv;
|
struct lib80211_ccmp_data *data = priv;
|
||||||
int keyidx;
|
int keyidx;
|
||||||
struct crypto_cipher *tfm = data->tfm;
|
struct crypto_cipher *tfm = data->tfm;
|
||||||
|
|
||||||
|
@ -418,9 +418,9 @@ static int ieee80211_ccmp_set_key(void *key, int len, u8 * seq, void *priv)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ieee80211_ccmp_get_key(void *key, int len, u8 * seq, void *priv)
|
static int lib80211_ccmp_get_key(void *key, int len, u8 * seq, void *priv)
|
||||||
{
|
{
|
||||||
struct ieee80211_ccmp_data *data = priv;
|
struct lib80211_ccmp_data *data = priv;
|
||||||
|
|
||||||
if (len < CCMP_TK_LEN)
|
if (len < CCMP_TK_LEN)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -441,9 +441,9 @@ static int ieee80211_ccmp_get_key(void *key, int len, u8 * seq, void *priv)
|
||||||
return CCMP_TK_LEN;
|
return CCMP_TK_LEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *ieee80211_ccmp_print_stats(char *p, void *priv)
|
static char *lib80211_ccmp_print_stats(char *p, void *priv)
|
||||||
{
|
{
|
||||||
struct ieee80211_ccmp_data *ccmp = priv;
|
struct lib80211_ccmp_data *ccmp = priv;
|
||||||
|
|
||||||
p += sprintf(p, "key[%d] alg=CCMP key_set=%d "
|
p += sprintf(p, "key[%d] alg=CCMP key_set=%d "
|
||||||
"tx_pn=%02x%02x%02x%02x%02x%02x "
|
"tx_pn=%02x%02x%02x%02x%02x%02x "
|
||||||
|
@ -461,32 +461,32 @@ static char *ieee80211_ccmp_print_stats(char *p, void *priv)
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct ieee80211_crypto_ops ieee80211_crypt_ccmp = {
|
static struct lib80211_crypto_ops lib80211_crypt_ccmp = {
|
||||||
.name = "CCMP",
|
.name = "CCMP",
|
||||||
.init = ieee80211_ccmp_init,
|
.init = lib80211_ccmp_init,
|
||||||
.deinit = ieee80211_ccmp_deinit,
|
.deinit = lib80211_ccmp_deinit,
|
||||||
.build_iv = ieee80211_ccmp_hdr,
|
.build_iv = lib80211_ccmp_hdr,
|
||||||
.encrypt_mpdu = ieee80211_ccmp_encrypt,
|
.encrypt_mpdu = lib80211_ccmp_encrypt,
|
||||||
.decrypt_mpdu = ieee80211_ccmp_decrypt,
|
.decrypt_mpdu = lib80211_ccmp_decrypt,
|
||||||
.encrypt_msdu = NULL,
|
.encrypt_msdu = NULL,
|
||||||
.decrypt_msdu = NULL,
|
.decrypt_msdu = NULL,
|
||||||
.set_key = ieee80211_ccmp_set_key,
|
.set_key = lib80211_ccmp_set_key,
|
||||||
.get_key = ieee80211_ccmp_get_key,
|
.get_key = lib80211_ccmp_get_key,
|
||||||
.print_stats = ieee80211_ccmp_print_stats,
|
.print_stats = lib80211_ccmp_print_stats,
|
||||||
.extra_mpdu_prefix_len = CCMP_HDR_LEN,
|
.extra_mpdu_prefix_len = CCMP_HDR_LEN,
|
||||||
.extra_mpdu_postfix_len = CCMP_MIC_LEN,
|
.extra_mpdu_postfix_len = CCMP_MIC_LEN,
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init ieee80211_crypto_ccmp_init(void)
|
static int __init lib80211_crypto_ccmp_init(void)
|
||||||
{
|
{
|
||||||
return ieee80211_register_crypto_ops(&ieee80211_crypt_ccmp);
|
return lib80211_register_crypto_ops(&lib80211_crypt_ccmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit ieee80211_crypto_ccmp_exit(void)
|
static void __exit lib80211_crypto_ccmp_exit(void)
|
||||||
{
|
{
|
||||||
ieee80211_unregister_crypto_ops(&ieee80211_crypt_ccmp);
|
lib80211_unregister_crypto_ops(&lib80211_crypt_ccmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init(ieee80211_crypto_ccmp_init);
|
module_init(lib80211_crypto_ccmp_init);
|
||||||
module_exit(ieee80211_crypto_ccmp_exit);
|
module_exit(lib80211_crypto_ccmp_exit);
|
|
@ -1,7 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* Host AP crypt: host-based TKIP encryption implementation for Host AP driver
|
* lib80211 crypt: host-based TKIP encryption implementation for lib80211
|
||||||
*
|
*
|
||||||
* Copyright (c) 2003-2004, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2003-2004, Jouni Malinen <j@w1.fi>
|
||||||
|
* Copyright (c) 2008, John W. Linville <linville@tuxdriver.com>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
@ -22,16 +23,20 @@
|
||||||
#include <linux/if_arp.h>
|
#include <linux/if_arp.h>
|
||||||
#include <asm/string.h>
|
#include <asm/string.h>
|
||||||
|
|
||||||
#include <net/ieee80211.h>
|
#include <linux/wireless.h>
|
||||||
|
#include <linux/ieee80211.h>
|
||||||
|
#include <net/iw_handler.h>
|
||||||
|
|
||||||
#include <linux/crypto.h>
|
#include <linux/crypto.h>
|
||||||
#include <linux/crc32.h>
|
#include <linux/crc32.h>
|
||||||
|
|
||||||
|
#include <net/lib80211.h>
|
||||||
|
|
||||||
MODULE_AUTHOR("Jouni Malinen");
|
MODULE_AUTHOR("Jouni Malinen");
|
||||||
MODULE_DESCRIPTION("Host AP crypt: TKIP");
|
MODULE_DESCRIPTION("lib80211 crypt: TKIP");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
struct ieee80211_tkip_data {
|
struct lib80211_tkip_data {
|
||||||
#define TKIP_KEY_LEN 32
|
#define TKIP_KEY_LEN 32
|
||||||
u8 key[TKIP_KEY_LEN];
|
u8 key[TKIP_KEY_LEN];
|
||||||
int key_set;
|
int key_set;
|
||||||
|
@ -65,23 +70,23 @@ struct ieee80211_tkip_data {
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned long ieee80211_tkip_set_flags(unsigned long flags, void *priv)
|
static unsigned long lib80211_tkip_set_flags(unsigned long flags, void *priv)
|
||||||
{
|
{
|
||||||
struct ieee80211_tkip_data *_priv = priv;
|
struct lib80211_tkip_data *_priv = priv;
|
||||||
unsigned long old_flags = _priv->flags;
|
unsigned long old_flags = _priv->flags;
|
||||||
_priv->flags = flags;
|
_priv->flags = flags;
|
||||||
return old_flags;
|
return old_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned long ieee80211_tkip_get_flags(void *priv)
|
static unsigned long lib80211_tkip_get_flags(void *priv)
|
||||||
{
|
{
|
||||||
struct ieee80211_tkip_data *_priv = priv;
|
struct lib80211_tkip_data *_priv = priv;
|
||||||
return _priv->flags;
|
return _priv->flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *ieee80211_tkip_init(int key_idx)
|
static void *lib80211_tkip_init(int key_idx)
|
||||||
{
|
{
|
||||||
struct ieee80211_tkip_data *priv;
|
struct lib80211_tkip_data *priv;
|
||||||
|
|
||||||
priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
|
priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
|
||||||
if (priv == NULL)
|
if (priv == NULL)
|
||||||
|
@ -92,7 +97,7 @@ static void *ieee80211_tkip_init(int key_idx)
|
||||||
priv->tx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
|
priv->tx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
|
||||||
CRYPTO_ALG_ASYNC);
|
CRYPTO_ALG_ASYNC);
|
||||||
if (IS_ERR(priv->tx_tfm_arc4)) {
|
if (IS_ERR(priv->tx_tfm_arc4)) {
|
||||||
printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
|
printk(KERN_DEBUG "lib80211_crypt_tkip: could not allocate "
|
||||||
"crypto API arc4\n");
|
"crypto API arc4\n");
|
||||||
priv->tx_tfm_arc4 = NULL;
|
priv->tx_tfm_arc4 = NULL;
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -101,7 +106,7 @@ static void *ieee80211_tkip_init(int key_idx)
|
||||||
priv->tx_tfm_michael = crypto_alloc_hash("michael_mic", 0,
|
priv->tx_tfm_michael = crypto_alloc_hash("michael_mic", 0,
|
||||||
CRYPTO_ALG_ASYNC);
|
CRYPTO_ALG_ASYNC);
|
||||||
if (IS_ERR(priv->tx_tfm_michael)) {
|
if (IS_ERR(priv->tx_tfm_michael)) {
|
||||||
printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
|
printk(KERN_DEBUG "lib80211_crypt_tkip: could not allocate "
|
||||||
"crypto API michael_mic\n");
|
"crypto API michael_mic\n");
|
||||||
priv->tx_tfm_michael = NULL;
|
priv->tx_tfm_michael = NULL;
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -110,7 +115,7 @@ static void *ieee80211_tkip_init(int key_idx)
|
||||||
priv->rx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
|
priv->rx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
|
||||||
CRYPTO_ALG_ASYNC);
|
CRYPTO_ALG_ASYNC);
|
||||||
if (IS_ERR(priv->rx_tfm_arc4)) {
|
if (IS_ERR(priv->rx_tfm_arc4)) {
|
||||||
printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
|
printk(KERN_DEBUG "lib80211_crypt_tkip: could not allocate "
|
||||||
"crypto API arc4\n");
|
"crypto API arc4\n");
|
||||||
priv->rx_tfm_arc4 = NULL;
|
priv->rx_tfm_arc4 = NULL;
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -119,7 +124,7 @@ static void *ieee80211_tkip_init(int key_idx)
|
||||||
priv->rx_tfm_michael = crypto_alloc_hash("michael_mic", 0,
|
priv->rx_tfm_michael = crypto_alloc_hash("michael_mic", 0,
|
||||||
CRYPTO_ALG_ASYNC);
|
CRYPTO_ALG_ASYNC);
|
||||||
if (IS_ERR(priv->rx_tfm_michael)) {
|
if (IS_ERR(priv->rx_tfm_michael)) {
|
||||||
printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
|
printk(KERN_DEBUG "lib80211_crypt_tkip: could not allocate "
|
||||||
"crypto API michael_mic\n");
|
"crypto API michael_mic\n");
|
||||||
priv->rx_tfm_michael = NULL;
|
priv->rx_tfm_michael = NULL;
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -143,9 +148,9 @@ static void *ieee80211_tkip_init(int key_idx)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ieee80211_tkip_deinit(void *priv)
|
static void lib80211_tkip_deinit(void *priv)
|
||||||
{
|
{
|
||||||
struct ieee80211_tkip_data *_priv = priv;
|
struct lib80211_tkip_data *_priv = priv;
|
||||||
if (_priv) {
|
if (_priv) {
|
||||||
if (_priv->tx_tfm_michael)
|
if (_priv->tx_tfm_michael)
|
||||||
crypto_free_hash(_priv->tx_tfm_michael);
|
crypto_free_hash(_priv->tx_tfm_michael);
|
||||||
|
@ -305,15 +310,15 @@ static void tkip_mixing_phase2(u8 * WEPSeed, const u8 * TK, const u16 * TTAK,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ieee80211_tkip_hdr(struct sk_buff *skb, int hdr_len,
|
static int lib80211_tkip_hdr(struct sk_buff *skb, int hdr_len,
|
||||||
u8 * rc4key, int keylen, void *priv)
|
u8 * rc4key, int keylen, void *priv)
|
||||||
{
|
{
|
||||||
struct ieee80211_tkip_data *tkey = priv;
|
struct lib80211_tkip_data *tkey = priv;
|
||||||
int len;
|
int len;
|
||||||
u8 *pos;
|
u8 *pos;
|
||||||
struct ieee80211_hdr_4addr *hdr;
|
struct ieee80211_hdr *hdr;
|
||||||
|
|
||||||
hdr = (struct ieee80211_hdr_4addr *)skb->data;
|
hdr = (struct ieee80211_hdr *)skb->data;
|
||||||
|
|
||||||
if (skb_headroom(skb) < 8 || skb->len < hdr_len)
|
if (skb_headroom(skb) < 8 || skb->len < hdr_len)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -351,9 +356,9 @@ static int ieee80211_tkip_hdr(struct sk_buff *skb, int hdr_len,
|
||||||
return 8;
|
return 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
|
static int lib80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
|
||||||
{
|
{
|
||||||
struct ieee80211_tkip_data *tkey = priv;
|
struct lib80211_tkip_data *tkey = priv;
|
||||||
struct blkcipher_desc desc = { .tfm = tkey->tx_tfm_arc4 };
|
struct blkcipher_desc desc = { .tfm = tkey->tx_tfm_arc4 };
|
||||||
int len;
|
int len;
|
||||||
u8 rc4key[16], *pos, *icv;
|
u8 rc4key[16], *pos, *icv;
|
||||||
|
@ -362,8 +367,8 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
|
||||||
|
|
||||||
if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) {
|
if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) {
|
||||||
if (net_ratelimit()) {
|
if (net_ratelimit()) {
|
||||||
struct ieee80211_hdr_4addr *hdr =
|
struct ieee80211_hdr *hdr =
|
||||||
(struct ieee80211_hdr_4addr *)skb->data;
|
(struct ieee80211_hdr *)skb->data;
|
||||||
printk(KERN_DEBUG ": TKIP countermeasures: dropped "
|
printk(KERN_DEBUG ": TKIP countermeasures: dropped "
|
||||||
"TX packet to %pM\n", hdr->addr1);
|
"TX packet to %pM\n", hdr->addr1);
|
||||||
}
|
}
|
||||||
|
@ -376,7 +381,7 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
|
||||||
len = skb->len - hdr_len;
|
len = skb->len - hdr_len;
|
||||||
pos = skb->data + hdr_len;
|
pos = skb->data + hdr_len;
|
||||||
|
|
||||||
if ((ieee80211_tkip_hdr(skb, hdr_len, rc4key, 16, priv)) < 0)
|
if ((lib80211_tkip_hdr(skb, hdr_len, rc4key, 16, priv)) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
icv = skb_put(skb, 4);
|
icv = skb_put(skb, 4);
|
||||||
|
@ -405,21 +410,21 @@ static inline int tkip_replay_check(u32 iv32_n, u16 iv16_n,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
|
static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
|
||||||
{
|
{
|
||||||
struct ieee80211_tkip_data *tkey = priv;
|
struct lib80211_tkip_data *tkey = priv;
|
||||||
struct blkcipher_desc desc = { .tfm = tkey->rx_tfm_arc4 };
|
struct blkcipher_desc desc = { .tfm = tkey->rx_tfm_arc4 };
|
||||||
u8 rc4key[16];
|
u8 rc4key[16];
|
||||||
u8 keyidx, *pos;
|
u8 keyidx, *pos;
|
||||||
u32 iv32;
|
u32 iv32;
|
||||||
u16 iv16;
|
u16 iv16;
|
||||||
struct ieee80211_hdr_4addr *hdr;
|
struct ieee80211_hdr *hdr;
|
||||||
u8 icv[4];
|
u8 icv[4];
|
||||||
u32 crc;
|
u32 crc;
|
||||||
struct scatterlist sg;
|
struct scatterlist sg;
|
||||||
int plen;
|
int plen;
|
||||||
|
|
||||||
hdr = (struct ieee80211_hdr_4addr *)skb->data;
|
hdr = (struct ieee80211_hdr *)skb->data;
|
||||||
|
|
||||||
if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) {
|
if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) {
|
||||||
if (net_ratelimit()) {
|
if (net_ratelimit()) {
|
||||||
|
@ -460,8 +465,8 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
|
||||||
pos += 8;
|
pos += 8;
|
||||||
|
|
||||||
if (tkip_replay_check(iv32, iv16, tkey->rx_iv32, tkey->rx_iv16)) {
|
if (tkip_replay_check(iv32, iv16, tkey->rx_iv32, tkey->rx_iv16)) {
|
||||||
if (ieee80211_ratelimit_debug(IEEE80211_DL_DROP)) {
|
if (net_ratelimit()) {
|
||||||
IEEE80211_DEBUG_DROP("TKIP: replay detected: STA=%pM"
|
printk(KERN_DEBUG "TKIP: replay detected: STA=%pM"
|
||||||
" previous TSC %08x%04x received TSC "
|
" previous TSC %08x%04x received TSC "
|
||||||
"%08x%04x\n", hdr->addr2,
|
"%08x%04x\n", hdr->addr2,
|
||||||
tkey->rx_iv32, tkey->rx_iv16, iv32, iv16);
|
tkey->rx_iv32, tkey->rx_iv16, iv32, iv16);
|
||||||
|
@ -500,8 +505,8 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
|
||||||
* it needs to be recalculated for the next packet. */
|
* it needs to be recalculated for the next packet. */
|
||||||
tkey->rx_phase1_done = 0;
|
tkey->rx_phase1_done = 0;
|
||||||
}
|
}
|
||||||
if (ieee80211_ratelimit_debug(IEEE80211_DL_DROP)) {
|
if (net_ratelimit()) {
|
||||||
IEEE80211_DEBUG_DROP("TKIP: ICV error detected: STA="
|
printk(KERN_DEBUG "TKIP: ICV error detected: STA="
|
||||||
"%pM\n", hdr->addr2);
|
"%pM\n", hdr->addr2);
|
||||||
}
|
}
|
||||||
tkey->dot11RSNAStatsTKIPICVErrors++;
|
tkey->dot11RSNAStatsTKIPICVErrors++;
|
||||||
|
@ -545,13 +550,11 @@ static int michael_mic(struct crypto_hash *tfm_michael, u8 * key, u8 * hdr,
|
||||||
|
|
||||||
static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr)
|
static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr)
|
||||||
{
|
{
|
||||||
struct ieee80211_hdr_4addr *hdr11;
|
struct ieee80211_hdr *hdr11;
|
||||||
u16 stype;
|
|
||||||
|
|
||||||
hdr11 = (struct ieee80211_hdr_4addr *)skb->data;
|
hdr11 = (struct ieee80211_hdr *)skb->data;
|
||||||
stype = WLAN_FC_GET_STYPE(le16_to_cpu(hdr11->frame_ctl));
|
|
||||||
|
|
||||||
switch (le16_to_cpu(hdr11->frame_ctl) &
|
switch (le16_to_cpu(hdr11->frame_control) &
|
||||||
(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
|
(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
|
||||||
case IEEE80211_FCTL_TODS:
|
case IEEE80211_FCTL_TODS:
|
||||||
memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */
|
memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */
|
||||||
|
@ -571,20 +574,19 @@ static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stype & IEEE80211_STYPE_QOS_DATA) {
|
if (ieee80211_is_data_qos(hdr11->frame_control)) {
|
||||||
const struct ieee80211_hdr_3addrqos *qoshdr =
|
hdr[12] = le16_to_cpu(*ieee80211_get_qos_ctl(hdr11))
|
||||||
(struct ieee80211_hdr_3addrqos *)skb->data;
|
& IEEE80211_QOS_CTL_TID_MASK;
|
||||||
hdr[12] = le16_to_cpu(qoshdr->qos_ctl) & IEEE80211_QCTL_TID;
|
|
||||||
} else
|
} else
|
||||||
hdr[12] = 0; /* priority */
|
hdr[12] = 0; /* priority */
|
||||||
|
|
||||||
hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */
|
hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ieee80211_michael_mic_add(struct sk_buff *skb, int hdr_len,
|
static int lib80211_michael_mic_add(struct sk_buff *skb, int hdr_len,
|
||||||
void *priv)
|
void *priv)
|
||||||
{
|
{
|
||||||
struct ieee80211_tkip_data *tkey = priv;
|
struct lib80211_tkip_data *tkey = priv;
|
||||||
u8 *pos;
|
u8 *pos;
|
||||||
|
|
||||||
if (skb_tailroom(skb) < 8 || skb->len < hdr_len) {
|
if (skb_tailroom(skb) < 8 || skb->len < hdr_len) {
|
||||||
|
@ -603,8 +605,8 @@ static int ieee80211_michael_mic_add(struct sk_buff *skb, int hdr_len,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ieee80211_michael_mic_failure(struct net_device *dev,
|
static void lib80211_michael_mic_failure(struct net_device *dev,
|
||||||
struct ieee80211_hdr_4addr *hdr,
|
struct ieee80211_hdr *hdr,
|
||||||
int keyidx)
|
int keyidx)
|
||||||
{
|
{
|
||||||
union iwreq_data wrqu;
|
union iwreq_data wrqu;
|
||||||
|
@ -624,10 +626,10 @@ static void ieee80211_michael_mic_failure(struct net_device *dev,
|
||||||
wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&ev);
|
wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx,
|
static int lib80211_michael_mic_verify(struct sk_buff *skb, int keyidx,
|
||||||
int hdr_len, void *priv)
|
int hdr_len, void *priv)
|
||||||
{
|
{
|
||||||
struct ieee80211_tkip_data *tkey = priv;
|
struct lib80211_tkip_data *tkey = priv;
|
||||||
u8 mic[8];
|
u8 mic[8];
|
||||||
|
|
||||||
if (!tkey->key_set)
|
if (!tkey->key_set)
|
||||||
|
@ -638,14 +640,14 @@ static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx,
|
||||||
skb->data + hdr_len, skb->len - 8 - hdr_len, mic))
|
skb->data + hdr_len, skb->len - 8 - hdr_len, mic))
|
||||||
return -1;
|
return -1;
|
||||||
if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) {
|
if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) {
|
||||||
struct ieee80211_hdr_4addr *hdr;
|
struct ieee80211_hdr *hdr;
|
||||||
hdr = (struct ieee80211_hdr_4addr *)skb->data;
|
hdr = (struct ieee80211_hdr *)skb->data;
|
||||||
printk(KERN_DEBUG "%s: Michael MIC verification failed for "
|
printk(KERN_DEBUG "%s: Michael MIC verification failed for "
|
||||||
"MSDU from %pM keyidx=%d\n",
|
"MSDU from %pM keyidx=%d\n",
|
||||||
skb->dev ? skb->dev->name : "N/A", hdr->addr2,
|
skb->dev ? skb->dev->name : "N/A", hdr->addr2,
|
||||||
keyidx);
|
keyidx);
|
||||||
if (skb->dev)
|
if (skb->dev)
|
||||||
ieee80211_michael_mic_failure(skb->dev, hdr, keyidx);
|
lib80211_michael_mic_failure(skb->dev, hdr, keyidx);
|
||||||
tkey->dot11RSNAStatsTKIPLocalMICFailures++;
|
tkey->dot11RSNAStatsTKIPLocalMICFailures++;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -660,9 +662,9 @@ static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ieee80211_tkip_set_key(void *key, int len, u8 * seq, void *priv)
|
static int lib80211_tkip_set_key(void *key, int len, u8 * seq, void *priv)
|
||||||
{
|
{
|
||||||
struct ieee80211_tkip_data *tkey = priv;
|
struct lib80211_tkip_data *tkey = priv;
|
||||||
int keyidx;
|
int keyidx;
|
||||||
struct crypto_hash *tfm = tkey->tx_tfm_michael;
|
struct crypto_hash *tfm = tkey->tx_tfm_michael;
|
||||||
struct crypto_blkcipher *tfm2 = tkey->tx_tfm_arc4;
|
struct crypto_blkcipher *tfm2 = tkey->tx_tfm_arc4;
|
||||||
|
@ -693,9 +695,9 @@ static int ieee80211_tkip_set_key(void *key, int len, u8 * seq, void *priv)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ieee80211_tkip_get_key(void *key, int len, u8 * seq, void *priv)
|
static int lib80211_tkip_get_key(void *key, int len, u8 * seq, void *priv)
|
||||||
{
|
{
|
||||||
struct ieee80211_tkip_data *tkey = priv;
|
struct lib80211_tkip_data *tkey = priv;
|
||||||
|
|
||||||
if (len < TKIP_KEY_LEN)
|
if (len < TKIP_KEY_LEN)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -722,9 +724,9 @@ static int ieee80211_tkip_get_key(void *key, int len, u8 * seq, void *priv)
|
||||||
return TKIP_KEY_LEN;
|
return TKIP_KEY_LEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *ieee80211_tkip_print_stats(char *p, void *priv)
|
static char *lib80211_tkip_print_stats(char *p, void *priv)
|
||||||
{
|
{
|
||||||
struct ieee80211_tkip_data *tkip = priv;
|
struct lib80211_tkip_data *tkip = priv;
|
||||||
p += sprintf(p, "key[%d] alg=TKIP key_set=%d "
|
p += sprintf(p, "key[%d] alg=TKIP key_set=%d "
|
||||||
"tx_pn=%02x%02x%02x%02x%02x%02x "
|
"tx_pn=%02x%02x%02x%02x%02x%02x "
|
||||||
"rx_pn=%02x%02x%02x%02x%02x%02x "
|
"rx_pn=%02x%02x%02x%02x%02x%02x "
|
||||||
|
@ -748,35 +750,35 @@ static char *ieee80211_tkip_print_stats(char *p, void *priv)
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct ieee80211_crypto_ops ieee80211_crypt_tkip = {
|
static struct lib80211_crypto_ops lib80211_crypt_tkip = {
|
||||||
.name = "TKIP",
|
.name = "TKIP",
|
||||||
.init = ieee80211_tkip_init,
|
.init = lib80211_tkip_init,
|
||||||
.deinit = ieee80211_tkip_deinit,
|
.deinit = lib80211_tkip_deinit,
|
||||||
.build_iv = ieee80211_tkip_hdr,
|
.build_iv = lib80211_tkip_hdr,
|
||||||
.encrypt_mpdu = ieee80211_tkip_encrypt,
|
.encrypt_mpdu = lib80211_tkip_encrypt,
|
||||||
.decrypt_mpdu = ieee80211_tkip_decrypt,
|
.decrypt_mpdu = lib80211_tkip_decrypt,
|
||||||
.encrypt_msdu = ieee80211_michael_mic_add,
|
.encrypt_msdu = lib80211_michael_mic_add,
|
||||||
.decrypt_msdu = ieee80211_michael_mic_verify,
|
.decrypt_msdu = lib80211_michael_mic_verify,
|
||||||
.set_key = ieee80211_tkip_set_key,
|
.set_key = lib80211_tkip_set_key,
|
||||||
.get_key = ieee80211_tkip_get_key,
|
.get_key = lib80211_tkip_get_key,
|
||||||
.print_stats = ieee80211_tkip_print_stats,
|
.print_stats = lib80211_tkip_print_stats,
|
||||||
.extra_mpdu_prefix_len = 4 + 4, /* IV + ExtIV */
|
.extra_mpdu_prefix_len = 4 + 4, /* IV + ExtIV */
|
||||||
.extra_mpdu_postfix_len = 4, /* ICV */
|
.extra_mpdu_postfix_len = 4, /* ICV */
|
||||||
.extra_msdu_postfix_len = 8, /* MIC */
|
.extra_msdu_postfix_len = 8, /* MIC */
|
||||||
.get_flags = ieee80211_tkip_get_flags,
|
.get_flags = lib80211_tkip_get_flags,
|
||||||
.set_flags = ieee80211_tkip_set_flags,
|
.set_flags = lib80211_tkip_set_flags,
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init ieee80211_crypto_tkip_init(void)
|
static int __init lib80211_crypto_tkip_init(void)
|
||||||
{
|
{
|
||||||
return ieee80211_register_crypto_ops(&ieee80211_crypt_tkip);
|
return lib80211_register_crypto_ops(&lib80211_crypt_tkip);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit ieee80211_crypto_tkip_exit(void)
|
static void __exit lib80211_crypto_tkip_exit(void)
|
||||||
{
|
{
|
||||||
ieee80211_unregister_crypto_ops(&ieee80211_crypt_tkip);
|
lib80211_unregister_crypto_ops(&lib80211_crypt_tkip);
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init(ieee80211_crypto_tkip_init);
|
module_init(lib80211_crypto_tkip_init);
|
||||||
module_exit(ieee80211_crypto_tkip_exit);
|
module_exit(lib80211_crypto_tkip_exit);
|
|
@ -1,7 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* Host AP crypt: host-based WEP encryption implementation for Host AP driver
|
* lib80211 crypt: host-based WEP encryption implementation for lib80211
|
||||||
*
|
*
|
||||||
* Copyright (c) 2002-2004, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2002-2004, Jouni Malinen <j@w1.fi>
|
||||||
|
* Copyright (c) 2008, John W. Linville <linville@tuxdriver.com>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
@ -19,16 +20,16 @@
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <asm/string.h>
|
#include <asm/string.h>
|
||||||
|
|
||||||
#include <net/ieee80211.h>
|
#include <net/lib80211.h>
|
||||||
|
|
||||||
#include <linux/crypto.h>
|
#include <linux/crypto.h>
|
||||||
#include <linux/crc32.h>
|
#include <linux/crc32.h>
|
||||||
|
|
||||||
MODULE_AUTHOR("Jouni Malinen");
|
MODULE_AUTHOR("Jouni Malinen");
|
||||||
MODULE_DESCRIPTION("Host AP crypt: WEP");
|
MODULE_DESCRIPTION("lib80211 crypt: WEP");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
struct prism2_wep_data {
|
struct lib80211_wep_data {
|
||||||
u32 iv;
|
u32 iv;
|
||||||
#define WEP_KEY_LEN 13
|
#define WEP_KEY_LEN 13
|
||||||
u8 key[WEP_KEY_LEN + 1];
|
u8 key[WEP_KEY_LEN + 1];
|
||||||
|
@ -38,9 +39,9 @@ struct prism2_wep_data {
|
||||||
struct crypto_blkcipher *rx_tfm;
|
struct crypto_blkcipher *rx_tfm;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void *prism2_wep_init(int keyidx)
|
static void *lib80211_wep_init(int keyidx)
|
||||||
{
|
{
|
||||||
struct prism2_wep_data *priv;
|
struct lib80211_wep_data *priv;
|
||||||
|
|
||||||
priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
|
priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
|
||||||
if (priv == NULL)
|
if (priv == NULL)
|
||||||
|
@ -49,7 +50,7 @@ static void *prism2_wep_init(int keyidx)
|
||||||
|
|
||||||
priv->tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
|
priv->tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
|
||||||
if (IS_ERR(priv->tx_tfm)) {
|
if (IS_ERR(priv->tx_tfm)) {
|
||||||
printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate "
|
printk(KERN_DEBUG "lib80211_crypt_wep: could not allocate "
|
||||||
"crypto API arc4\n");
|
"crypto API arc4\n");
|
||||||
priv->tx_tfm = NULL;
|
priv->tx_tfm = NULL;
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -57,7 +58,7 @@ static void *prism2_wep_init(int keyidx)
|
||||||
|
|
||||||
priv->rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
|
priv->rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
|
||||||
if (IS_ERR(priv->rx_tfm)) {
|
if (IS_ERR(priv->rx_tfm)) {
|
||||||
printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate "
|
printk(KERN_DEBUG "lib80211_crypt_wep: could not allocate "
|
||||||
"crypto API arc4\n");
|
"crypto API arc4\n");
|
||||||
priv->rx_tfm = NULL;
|
priv->rx_tfm = NULL;
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -78,9 +79,9 @@ static void *prism2_wep_init(int keyidx)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void prism2_wep_deinit(void *priv)
|
static void lib80211_wep_deinit(void *priv)
|
||||||
{
|
{
|
||||||
struct prism2_wep_data *_priv = priv;
|
struct lib80211_wep_data *_priv = priv;
|
||||||
if (_priv) {
|
if (_priv) {
|
||||||
if (_priv->tx_tfm)
|
if (_priv->tx_tfm)
|
||||||
crypto_free_blkcipher(_priv->tx_tfm);
|
crypto_free_blkcipher(_priv->tx_tfm);
|
||||||
|
@ -91,10 +92,10 @@ static void prism2_wep_deinit(void *priv)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add WEP IV/key info to a frame that has at least 4 bytes of headroom */
|
/* Add WEP IV/key info to a frame that has at least 4 bytes of headroom */
|
||||||
static int prism2_wep_build_iv(struct sk_buff *skb, int hdr_len,
|
static int lib80211_wep_build_iv(struct sk_buff *skb, int hdr_len,
|
||||||
u8 *key, int keylen, void *priv)
|
u8 *key, int keylen, void *priv)
|
||||||
{
|
{
|
||||||
struct prism2_wep_data *wep = priv;
|
struct lib80211_wep_data *wep = priv;
|
||||||
u32 klen, len;
|
u32 klen, len;
|
||||||
u8 *pos;
|
u8 *pos;
|
||||||
|
|
||||||
|
@ -134,21 +135,21 @@ static int prism2_wep_build_iv(struct sk_buff *skb, int hdr_len,
|
||||||
*
|
*
|
||||||
* WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data))
|
* WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data))
|
||||||
*/
|
*/
|
||||||
static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
|
static int lib80211_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
|
||||||
{
|
{
|
||||||
struct prism2_wep_data *wep = priv;
|
struct lib80211_wep_data *wep = priv;
|
||||||
struct blkcipher_desc desc = { .tfm = wep->tx_tfm };
|
struct blkcipher_desc desc = { .tfm = wep->tx_tfm };
|
||||||
u32 crc, klen, len;
|
u32 crc, klen, len;
|
||||||
u8 *pos, *icv;
|
u8 *pos, *icv;
|
||||||
struct scatterlist sg;
|
struct scatterlist sg;
|
||||||
u8 key[WEP_KEY_LEN + 3];
|
u8 key[WEP_KEY_LEN + 3];
|
||||||
|
|
||||||
/* other checks are in prism2_wep_build_iv */
|
/* other checks are in lib80211_wep_build_iv */
|
||||||
if (skb_tailroom(skb) < 4)
|
if (skb_tailroom(skb) < 4)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* add the IV to the frame */
|
/* add the IV to the frame */
|
||||||
if (prism2_wep_build_iv(skb, hdr_len, NULL, 0, priv))
|
if (lib80211_wep_build_iv(skb, hdr_len, NULL, 0, priv))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Copy the IV into the first 3 bytes of the key */
|
/* Copy the IV into the first 3 bytes of the key */
|
||||||
|
@ -181,9 +182,9 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
|
||||||
* Returns 0 if frame was decrypted successfully and ICV was correct and -1 on
|
* Returns 0 if frame was decrypted successfully and ICV was correct and -1 on
|
||||||
* failure. If frame is OK, IV and ICV will be removed.
|
* failure. If frame is OK, IV and ICV will be removed.
|
||||||
*/
|
*/
|
||||||
static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
|
static int lib80211_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
|
||||||
{
|
{
|
||||||
struct prism2_wep_data *wep = priv;
|
struct lib80211_wep_data *wep = priv;
|
||||||
struct blkcipher_desc desc = { .tfm = wep->rx_tfm };
|
struct blkcipher_desc desc = { .tfm = wep->rx_tfm };
|
||||||
u32 crc, klen, plen;
|
u32 crc, klen, plen;
|
||||||
u8 key[WEP_KEY_LEN + 3];
|
u8 key[WEP_KEY_LEN + 3];
|
||||||
|
@ -232,9 +233,9 @@ static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int prism2_wep_set_key(void *key, int len, u8 * seq, void *priv)
|
static int lib80211_wep_set_key(void *key, int len, u8 * seq, void *priv)
|
||||||
{
|
{
|
||||||
struct prism2_wep_data *wep = priv;
|
struct lib80211_wep_data *wep = priv;
|
||||||
|
|
||||||
if (len < 0 || len > WEP_KEY_LEN)
|
if (len < 0 || len > WEP_KEY_LEN)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -245,9 +246,9 @@ static int prism2_wep_set_key(void *key, int len, u8 * seq, void *priv)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int prism2_wep_get_key(void *key, int len, u8 * seq, void *priv)
|
static int lib80211_wep_get_key(void *key, int len, u8 * seq, void *priv)
|
||||||
{
|
{
|
||||||
struct prism2_wep_data *wep = priv;
|
struct lib80211_wep_data *wep = priv;
|
||||||
|
|
||||||
if (len < wep->key_len)
|
if (len < wep->key_len)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -257,39 +258,39 @@ static int prism2_wep_get_key(void *key, int len, u8 * seq, void *priv)
|
||||||
return wep->key_len;
|
return wep->key_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *prism2_wep_print_stats(char *p, void *priv)
|
static char *lib80211_wep_print_stats(char *p, void *priv)
|
||||||
{
|
{
|
||||||
struct prism2_wep_data *wep = priv;
|
struct lib80211_wep_data *wep = priv;
|
||||||
p += sprintf(p, "key[%d] alg=WEP len=%d\n", wep->key_idx, wep->key_len);
|
p += sprintf(p, "key[%d] alg=WEP len=%d\n", wep->key_idx, wep->key_len);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct ieee80211_crypto_ops ieee80211_crypt_wep = {
|
static struct lib80211_crypto_ops lib80211_crypt_wep = {
|
||||||
.name = "WEP",
|
.name = "WEP",
|
||||||
.init = prism2_wep_init,
|
.init = lib80211_wep_init,
|
||||||
.deinit = prism2_wep_deinit,
|
.deinit = lib80211_wep_deinit,
|
||||||
.build_iv = prism2_wep_build_iv,
|
.build_iv = lib80211_wep_build_iv,
|
||||||
.encrypt_mpdu = prism2_wep_encrypt,
|
.encrypt_mpdu = lib80211_wep_encrypt,
|
||||||
.decrypt_mpdu = prism2_wep_decrypt,
|
.decrypt_mpdu = lib80211_wep_decrypt,
|
||||||
.encrypt_msdu = NULL,
|
.encrypt_msdu = NULL,
|
||||||
.decrypt_msdu = NULL,
|
.decrypt_msdu = NULL,
|
||||||
.set_key = prism2_wep_set_key,
|
.set_key = lib80211_wep_set_key,
|
||||||
.get_key = prism2_wep_get_key,
|
.get_key = lib80211_wep_get_key,
|
||||||
.print_stats = prism2_wep_print_stats,
|
.print_stats = lib80211_wep_print_stats,
|
||||||
.extra_mpdu_prefix_len = 4, /* IV */
|
.extra_mpdu_prefix_len = 4, /* IV */
|
||||||
.extra_mpdu_postfix_len = 4, /* ICV */
|
.extra_mpdu_postfix_len = 4, /* ICV */
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init ieee80211_crypto_wep_init(void)
|
static int __init lib80211_crypto_wep_init(void)
|
||||||
{
|
{
|
||||||
return ieee80211_register_crypto_ops(&ieee80211_crypt_wep);
|
return lib80211_register_crypto_ops(&lib80211_crypt_wep);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit ieee80211_crypto_wep_exit(void)
|
static void __exit lib80211_crypto_wep_exit(void)
|
||||||
{
|
{
|
||||||
ieee80211_unregister_crypto_ops(&ieee80211_crypt_wep);
|
lib80211_unregister_crypto_ops(&lib80211_crypt_wep);
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init(ieee80211_crypto_wep_init);
|
module_init(lib80211_crypto_wep_init);
|
||||||
module_exit(ieee80211_crypto_wep_exit);
|
module_exit(lib80211_crypto_wep_exit);
|
Loading…
Reference in a new issue