Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4f975b32 authored by Jeff Garzik's avatar Jeff Garzik
Browse files
parents 0cc349d1 d1b46b0f
Loading
Loading
Loading
Loading
+166 −3
Original line number Diff line number Diff line
@@ -220,6 +220,7 @@ struct ieee80211_snap_hdr {
/* Authentication algorithms */
#define WLAN_AUTH_OPEN 0
#define WLAN_AUTH_SHARED_KEY 1
#define WLAN_AUTH_LEAP 2

#define WLAN_AUTH_CHALLENGE_LEN 128

@@ -299,6 +300,23 @@ enum ieee80211_reasoncode {
	WLAN_REASON_CIPHER_SUITE_REJECTED = 24,
};

/* Action categories - 802.11h */
enum ieee80211_actioncategories {
	WLAN_ACTION_SPECTRUM_MGMT = 0,
	/* Reserved 1-127  */
	/* Error    128-255 */
};

/* Action details - 802.11h */
enum ieee80211_actiondetails {
	WLAN_ACTION_CATEGORY_MEASURE_REQUEST = 0,
	WLAN_ACTION_CATEGORY_MEASURE_REPORT = 1,
	WLAN_ACTION_CATEGORY_TPC_REQUEST = 2,
	WLAN_ACTION_CATEGORY_TPC_REPORT = 3,
	WLAN_ACTION_CATEGORY_CHANNEL_SWITCH = 4,
	/* 5 - 255 Reserved */
};

#define IEEE80211_STATMASK_SIGNAL (1<<0)
#define IEEE80211_STATMASK_RSSI (1<<1)
#define IEEE80211_STATMASK_NOISE (1<<2)
@@ -377,6 +395,8 @@ struct ieee80211_rx_stats {
	u8 mask;
	u8 freq;
	u16 len;
	u64 tsf;
	u32 beacon_time;
};

/* IEEE 802.11 requires that STA supports concurrent reception of at least
@@ -608,6 +628,28 @@ struct ieee80211_auth {
	struct ieee80211_info_element info_element[0];
} __attribute__ ((packed));

struct ieee80211_channel_switch {
	u8 id;
	u8 len;
	u8 mode;
	u8 channel;
	u8 count;
} __attribute__ ((packed));

struct ieee80211_action {
	struct ieee80211_hdr_3addr header;
	u8 category;
	u8 action;
	union {
		struct ieee80211_action_exchange {
			u8 token;
			struct ieee80211_info_element info_element[0];
		} exchange;
		struct ieee80211_channel_switch channel_switch;

	} format;
} __attribute__ ((packed));

struct ieee80211_disassoc {
	struct ieee80211_hdr_3addr header;
	__le16 reason;
@@ -692,7 +734,15 @@ struct ieee80211_txb {
/* QoS structure */
#define NETWORK_HAS_QOS_PARAMETERS      (1<<3)
#define NETWORK_HAS_QOS_INFORMATION     (1<<4)
#define NETWORK_HAS_QOS_MASK            (NETWORK_HAS_QOS_PARAMETERS | NETWORK_HAS_QOS_INFORMATION)
#define NETWORK_HAS_QOS_MASK            (NETWORK_HAS_QOS_PARAMETERS | \
					 NETWORK_HAS_QOS_INFORMATION)

/* 802.11h */
#define NETWORK_HAS_POWER_CONSTRAINT    (1<<5)
#define NETWORK_HAS_CSA                 (1<<6)
#define NETWORK_HAS_QUIET               (1<<7)
#define NETWORK_HAS_IBSS_DFS            (1<<8)
#define NETWORK_HAS_TPC_REPORT          (1<<9)

#define QOS_QUEUE_NUM                   4
#define QOS_OUI_LEN                     3
@@ -748,6 +798,91 @@ struct ieee80211_tim_parameters {

/*******************************************************/

enum {				/* ieee80211_basic_report.map */
	IEEE80211_BASIC_MAP_BSS = (1 << 0),
	IEEE80211_BASIC_MAP_OFDM = (1 << 1),
	IEEE80211_BASIC_MAP_UNIDENTIFIED = (1 << 2),
	IEEE80211_BASIC_MAP_RADAR = (1 << 3),
	IEEE80211_BASIC_MAP_UNMEASURED = (1 << 4),
	/* Bits 5-7 are reserved */

};
struct ieee80211_basic_report {
	u8 channel;
	__le64 start_time;
	__le16 duration;
	u8 map;
} __attribute__ ((packed));

enum {				/* ieee80211_measurement_request.mode */
	/* Bit 0 is reserved */
	IEEE80211_MEASUREMENT_ENABLE = (1 << 1),
	IEEE80211_MEASUREMENT_REQUEST = (1 << 2),
	IEEE80211_MEASUREMENT_REPORT = (1 << 3),
	/* Bits 4-7 are reserved */
};

enum {
	IEEE80211_REPORT_BASIC = 0,	/* required */
	IEEE80211_REPORT_CCA = 1,	/* optional */
	IEEE80211_REPORT_RPI = 2,	/* optional */
	/* 3-255 reserved */
};

struct ieee80211_measurement_params {
	u8 channel;
	__le64 start_time;
	__le16 duration;
} __attribute__ ((packed));

struct ieee80211_measurement_request {
	struct ieee80211_info_element ie;
	u8 token;
	u8 mode;
	u8 type;
	struct ieee80211_measurement_params params[0];
} __attribute__ ((packed));

struct ieee80211_measurement_report {
	struct ieee80211_info_element ie;
	u8 token;
	u8 mode;
	u8 type;
	union {
		struct ieee80211_basic_report basic[0];
	} u;
} __attribute__ ((packed));

struct ieee80211_tpc_report {
	u8 transmit_power;
	u8 link_margin;
} __attribute__ ((packed));

struct ieee80211_channel_map {
	u8 channel;
	u8 map;
} __attribute__ ((packed));

struct ieee80211_ibss_dfs {
	struct ieee80211_info_element ie;
	u8 owner[ETH_ALEN];
	u8 recovery_interval;
	struct ieee80211_channel_map channel_map[0];
};

struct ieee80211_csa {
	u8 mode;
	u8 channel;
	u8 count;
} __attribute__ ((packed));

struct ieee80211_quiet {
	u8 count;
	u8 period;
	u8 duration;
	u8 offset;
} __attribute__ ((packed));

struct ieee80211_network {
	/* These entries are used to identify a unique network */
	u8 bssid[ETH_ALEN];
@@ -767,7 +902,7 @@ struct ieee80211_network {
	u8 rates_ex_len;
	unsigned long last_scanned;
	u8 mode;
	u8 flags;
	u32 flags;
	u32 last_associate;
	u32 time_stamp[2];
	u16 beacon_interval;
@@ -779,6 +914,25 @@ struct ieee80211_network {
	u8 rsn_ie[MAX_WPA_IE_LEN];
	size_t rsn_ie_len;
	struct ieee80211_tim_parameters tim;

	/* 802.11h info */

	/* Power Constraint - mandatory if spctrm mgmt required */
	u8 power_constraint;

	/* TPC Report - mandatory if spctrm mgmt required */
	struct ieee80211_tpc_report tpc_report;

	/* IBSS DFS - mandatory if spctrm mgmt required and IBSS
	 * NOTE: This is variable length and so must be allocated dynamically */
	struct ieee80211_ibss_dfs *ibss_dfs;

	/* Channel Switch Announcement - optional if spctrm mgmt required */
	struct ieee80211_csa csa;

	/* Quiet - optional if spctrm mgmt required */
	struct ieee80211_quiet quiet;

	struct list_head list;
};

@@ -924,7 +1078,10 @@ struct ieee80211_device {
	int (*handle_auth) (struct net_device * dev,
			    struct ieee80211_auth * auth);
	int (*handle_deauth) (struct net_device * dev,
			      struct ieee80211_auth * auth);
			      struct ieee80211_deauth * auth);
	int (*handle_action) (struct net_device * dev,
			      struct ieee80211_action * action,
			      struct ieee80211_rx_stats * stats);
	int (*handle_disassoc) (struct net_device * dev,
				struct ieee80211_disassoc * assoc);
	int (*handle_beacon) (struct net_device * dev,
@@ -1093,6 +1250,7 @@ extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
extern void ieee80211_rx_mgt(struct ieee80211_device *ieee,
			     struct ieee80211_hdr_4addr *header,
			     struct ieee80211_rx_stats *stats);
extern void ieee80211_network_reset(struct ieee80211_network *network);

/* ieee80211_geo.c */
extern const struct ieee80211_geo *ieee80211_get_geo(struct ieee80211_device
@@ -1105,6 +1263,11 @@ extern int ieee80211_is_valid_channel(struct ieee80211_device *ieee,
extern int ieee80211_channel_to_index(struct ieee80211_device *ieee,
				      u8 channel);
extern u8 ieee80211_freq_to_channel(struct ieee80211_device *ieee, u32 freq);
extern u8 ieee80211_get_channel_flags(struct ieee80211_device *ieee,
				      u8 channel);
extern const struct ieee80211_channel *ieee80211_get_channel(struct
							     ieee80211_device
							     *ieee, u8 channel);

/* ieee80211_wx.c */
extern int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
+2 −1
Original line number Diff line number Diff line
@@ -47,7 +47,8 @@ struct ieee80211_crypto_ops {
	/* deinitialize crypto context and free allocated private data */
	void (*deinit) (void *priv);

	int (*build_iv) (struct sk_buff * skb, int hdr_len, 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
+5 −6
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@
#include <linux/string.h>
#include <net/ieee80211.h>


MODULE_AUTHOR("Jouni Malinen");
MODULE_DESCRIPTION("HostAP crypto");
MODULE_LICENSE("GPL");
+6 −2
Original line number Diff line number Diff line
@@ -190,7 +190,8 @@ static void ccmp_init_blocks(struct crypto_tfm *tfm,
	ieee80211_ccmp_aes_encrypt(tfm, b0, s0);
}

static int ieee80211_ccmp_hdr(struct sk_buff *skb, int hdr_len, void *priv)
static int ieee80211_ccmp_hdr(struct sk_buff *skb, int hdr_len,
			      u8 *aeskey, int keylen, void *priv)
{
	struct ieee80211_ccmp_data *key = priv;
	int i;
@@ -199,6 +200,9 @@ static int ieee80211_ccmp_hdr(struct sk_buff *skb, int hdr_len, void *priv)
	if (skb_headroom(skb) < CCMP_HDR_LEN || skb->len < hdr_len)
		return -1;

	if (aeskey != NULL && keylen >= CCMP_TK_LEN)
		memcpy(aeskey, key->key, CCMP_TK_LEN);

	pos = skb_push(skb, CCMP_HDR_LEN);
	memmove(pos, pos + CCMP_HDR_LEN, hdr_len);
	pos += hdr_len;
@@ -238,7 +242,7 @@ static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
		return -1;

	data_len = skb->len - hdr_len;
	len = ieee80211_ccmp_hdr(skb, hdr_len, priv);
	len = ieee80211_ccmp_hdr(skb, hdr_len, NULL, 0, priv);
	if (len < 0)
		return -1;

+28 −28
Original line number Diff line number Diff line
@@ -80,10 +80,9 @@ static void *ieee80211_tkip_init(int key_idx)
{
	struct ieee80211_tkip_data *priv;

	priv = kmalloc(sizeof(*priv), GFP_ATOMIC);
	priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
	if (priv == NULL)
		goto fail;
	memset(priv, 0, sizeof(*priv));

	priv->key_idx = key_idx;

@@ -271,34 +270,33 @@ static void tkip_mixing_phase2(u8 * WEPSeed, const u8 * TK, const u16 * TTAK,
#endif
}

static u8 *ieee80211_tkip_hdr(struct sk_buff *skb, int hdr_len, void *priv)
static int ieee80211_tkip_hdr(struct sk_buff *skb, int hdr_len,
			      u8 * rc4key, int keylen, void *priv)
{
	struct ieee80211_tkip_data *tkey = priv;
	int len;
	u8 *rc4key, *pos, *icv;
	u8 *pos;
	struct ieee80211_hdr_4addr *hdr;
	u32 crc;

	hdr = (struct ieee80211_hdr_4addr *)skb->data;

	if (skb_headroom(skb) < 8 || skb->len < hdr_len)
		return NULL;
		return -1;

	if (rc4key == NULL || keylen < 16)
		return -1;

	if (!tkey->tx_phase1_done) {
		tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2,
				   tkey->tx_iv32);
		tkey->tx_phase1_done = 1;
	}
	rc4key = kmalloc(16, GFP_ATOMIC);
	if (!rc4key)
		return NULL;
	tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16);

	len = skb->len - hdr_len;
	pos = skb_push(skb, 8);
	memmove(pos, pos + 8, hdr_len);
	pos += hdr_len;
	icv = skb_put(skb, 4);

	*pos++ = *rc4key;
	*pos++ = *(rc4key + 1);
@@ -309,28 +307,28 @@ static u8 *ieee80211_tkip_hdr(struct sk_buff *skb, int hdr_len, void *priv)
	*pos++ = (tkey->tx_iv32 >> 16) & 0xff;
	*pos++ = (tkey->tx_iv32 >> 24) & 0xff;

	crc = ~crc32_le(~0, pos, len);
	icv[0] = crc;
	icv[1] = crc >> 8;
	icv[2] = crc >> 16;
	icv[3] = crc >> 24;
	tkey->tx_iv16++;
	if (tkey->tx_iv16 == 0) {
		tkey->tx_phase1_done = 0;
		tkey->tx_iv32++;
	}

	return rc4key;
	return 8;
}

static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
{
	struct ieee80211_tkip_data *tkey = priv;
	int len;
	const u8 *rc4key;
	u8 *pos;
	u8 rc4key[16], *pos, *icv;
	u32 crc;
	struct scatterlist sg;

	if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) {
		if (net_ratelimit()) {
			struct ieee80211_hdr_4addr *hdr =
			    (struct ieee80211_hdr_4addr *)skb->data;
			printk(KERN_DEBUG "TKIP countermeasures: dropped "
			printk(KERN_DEBUG ": TKIP countermeasures: dropped "
			       "TX packet to " MAC_FMT "\n",
			       MAC_ARG(hdr->addr1));
		}
@@ -343,22 +341,23 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
	len = skb->len - hdr_len;
	pos = skb->data + hdr_len;

	rc4key = ieee80211_tkip_hdr(skb, hdr_len, priv);
	if (!rc4key)
	if ((ieee80211_tkip_hdr(skb, hdr_len, rc4key, 16, priv)) < 0)
		return -1;

	icv = skb_put(skb, 4);

	crc = ~crc32_le(~0, pos, len);
	icv[0] = crc;
	icv[1] = crc >> 8;
	icv[2] = crc >> 16;
	icv[3] = crc >> 24;

	crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16);
	sg.page = virt_to_page(pos);
	sg.offset = offset_in_page(pos);
	sg.length = len + 4;
	crypto_cipher_encrypt(tkey->tfm_arc4, &sg, &sg, len + 4);

	tkey->tx_iv16++;
	if (tkey->tx_iv16 == 0) {
		tkey->tx_phase1_done = 0;
		tkey->tx_iv32++;
	}

	return 0;
}

@@ -379,7 +378,7 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)

	if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) {
		if (net_ratelimit()) {
			printk(KERN_DEBUG "TKIP countermeasures: dropped "
			printk(KERN_DEBUG ": TKIP countermeasures: dropped "
			       "received packet from " MAC_FMT "\n",
			       MAC_ARG(hdr->addr2));
		}
@@ -695,6 +694,7 @@ static struct ieee80211_crypto_ops ieee80211_crypt_tkip = {
	.name = "TKIP",
	.init = ieee80211_tkip_init,
	.deinit = ieee80211_tkip_deinit,
	.build_iv = ieee80211_tkip_hdr,
	.encrypt_mpdu = ieee80211_tkip_encrypt,
	.decrypt_mpdu = ieee80211_tkip_decrypt,
	.encrypt_msdu = ieee80211_michael_mic_add,
Loading