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

Commit 31b59eae authored by James Ketrenos's avatar James Ketrenos Committed by Jeff Garzik
Browse files

[PATCH] ieee80211: Added handle_deauth() callback, enhanced tkip/ccmp support...


[PATCH] ieee80211: Added handle_deauth() callback, enhanced tkip/ccmp support of varying hw/sw offload

tree de81b55e78e85997642c651ea677078d0554a14f
parent c8030da8c159f8b82712172a6748a42523aea83a
author James Ketrenos <jketreno@linux.intel.com> 1127104380 -0500
committer James Ketrenos <jketreno@linux.intel.com> 1127315225 -0500

Added handle_deauth() callback.
Enhanced crypt_{tkip,ccmp} to support varying splits of HW/SW offload.
Changed channel freq to u32 from u16.
Signed-off-by: default avatarJeff Garzik <jgarzik@pobox.com>
parent 31696160
Loading
Loading
Loading
Loading
+4 −1
Original line number Original line Diff line number Diff line
@@ -808,7 +808,7 @@ enum {
};
};


struct ieee80211_channel {
struct ieee80211_channel {
	u16 freq;
	u32 freq;
	u8 channel;
	u8 channel;
	u8 flags;
	u8 flags;
	u8 max_power;
	u8 max_power;
@@ -862,6 +862,7 @@ struct ieee80211_device {
	int host_mc_decrypt;
	int host_mc_decrypt;


	int host_open_frag;
	int host_open_frag;
	int host_build_iv;
	int ieee802_1x;		/* is IEEE 802.1X used */
	int ieee802_1x;		/* is IEEE 802.1X used */


	/* WPA data */
	/* WPA data */
@@ -914,6 +915,8 @@ struct ieee80211_device {
	/* Typical STA methods */
	/* Typical STA methods */
	int (*handle_auth) (struct net_device * dev,
	int (*handle_auth) (struct net_device * dev,
			    struct ieee80211_auth * auth);
			    struct ieee80211_auth * auth);
	int (*handle_deauth) (struct net_device * dev,
			      struct ieee80211_auth * auth);
	int (*handle_disassoc) (struct net_device * dev,
	int (*handle_disassoc) (struct net_device * dev,
				struct ieee80211_disassoc * assoc);
				struct ieee80211_disassoc * assoc);
	int (*handle_beacon) (struct net_device * dev,
	int (*handle_beacon) (struct net_device * dev,
+2 −0
Original line number Original line Diff line number Diff line
@@ -36,6 +36,8 @@ struct ieee80211_crypto_ops {
	/* deinitialize crypto context and free allocated private data */
	/* deinitialize crypto context and free allocated private data */
	void (*deinit) (void *priv);
	void (*deinit) (void *priv);


	int (*build_iv) (struct sk_buff * skb, int hdr_len, void *priv);

	/* encrypt/decrypt return < 0 on error or >= 0 on success. The return
	/* encrypt/decrypt return < 0 on error or >= 0 on success. The return
	 * value from decrypt_mpdu is passed as the keyidx value for
	 * value from decrypt_mpdu is passed as the keyidx value for
	 * decrypt_msdu. skb must have enough head and tail room for the
	 * decrypt_msdu. skb must have enough head and tail room for the
+29 −12
Original line number Original line Diff line number Diff line
@@ -191,26 +191,18 @@ static void ccmp_init_blocks(struct crypto_tfm *tfm,
	ieee80211_ccmp_aes_encrypt(tfm, b0, s0);
	ieee80211_ccmp_aes_encrypt(tfm, b0, s0);
}
}


static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
static int ieee80211_ccmp_hdr(struct sk_buff *skb, int hdr_len, void *priv)
{
{
	struct ieee80211_ccmp_data *key = priv;
	struct ieee80211_ccmp_data *key = priv;
	int data_len, i, blocks, last, len;
	int i;
	u8 *pos, *mic;
	u8 *pos;
	struct ieee80211_hdr_4addr *hdr;
	u8 *b0 = key->tx_b0;
	u8 *b = key->tx_b;
	u8 *e = key->tx_e;
	u8 *s0 = key->tx_s0;


	if (skb_headroom(skb) < CCMP_HDR_LEN ||
	if (skb_headroom(skb) < CCMP_HDR_LEN || skb->len < hdr_len)
	    skb_tailroom(skb) < CCMP_MIC_LEN || skb->len < hdr_len)
		return -1;
		return -1;


	data_len = skb->len - hdr_len;
	pos = skb_push(skb, CCMP_HDR_LEN);
	pos = skb_push(skb, CCMP_HDR_LEN);
	memmove(pos, pos + CCMP_HDR_LEN, hdr_len);
	memmove(pos, pos + CCMP_HDR_LEN, hdr_len);
	pos += hdr_len;
	pos += hdr_len;
	mic = skb_put(skb, CCMP_MIC_LEN);


	i = CCMP_PN_LEN - 1;
	i = CCMP_PN_LEN - 1;
	while (i >= 0) {
	while (i >= 0) {
@@ -229,6 +221,30 @@ static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
	*pos++ = key->tx_pn[1];
	*pos++ = key->tx_pn[1];
	*pos++ = key->tx_pn[0];
	*pos++ = key->tx_pn[0];


	return CCMP_HDR_LEN;
}

static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
{
	struct ieee80211_ccmp_data *key = priv;
	int data_len, i, blocks, last, len;
	u8 *pos, *mic;
	struct ieee80211_hdr_4addr *hdr;
	u8 *b0 = key->tx_b0;
	u8 *b = key->tx_b;
	u8 *e = key->tx_e;
	u8 *s0 = key->tx_s0;

	if (skb_tailroom(skb) < CCMP_MIC_LEN || skb->len < hdr_len)
		return -1;

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

	pos = skb->data + hdr_len + CCMP_HDR_LEN;
	mic = skb_put(skb, CCMP_MIC_LEN);
	hdr = (struct ieee80211_hdr_4addr *)skb->data;
	hdr = (struct ieee80211_hdr_4addr *)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);


@@ -429,6 +445,7 @@ static struct ieee80211_crypto_ops ieee80211_crypt_ccmp = {
	.name = "CCMP",
	.name = "CCMP",
	.init = ieee80211_ccmp_init,
	.init = ieee80211_ccmp_init,
	.deinit = ieee80211_ccmp_deinit,
	.deinit = ieee80211_ccmp_deinit,
	.build_iv = ieee80211_ccmp_hdr,
	.encrypt_mpdu = ieee80211_ccmp_encrypt,
	.encrypt_mpdu = ieee80211_ccmp_encrypt,
	.decrypt_mpdu = ieee80211_ccmp_decrypt,
	.decrypt_mpdu = ieee80211_ccmp_decrypt,
	.encrypt_msdu = NULL,
	.encrypt_msdu = NULL,
+42 −18
Original line number Original line Diff line number Diff line
@@ -260,35 +260,27 @@ static void tkip_mixing_phase2(u8 * WEPSeed, const u8 * TK, const u16 * TTAK,
#endif
#endif
}
}


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


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


	if (tkey->ieee->tkip_countermeasures) {
	if (skb_headroom(skb) < 8 || skb->len < hdr_len)
		if (net_ratelimit()) {
		return NULL;
			printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
			       "TX packet to " MAC_FMT "\n",
			       tkey->ieee->dev->name, MAC_ARG(hdr->addr1));
		}
		return -1;
	}

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


	if (!tkey->tx_phase1_done) {
	if (!tkey->tx_phase1_done) {
		tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2,
		tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2,
				   tkey->tx_iv32);
				   tkey->tx_iv32);
		tkey->tx_phase1_done = 1;
		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);
	tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16);


	len = skb->len - hdr_len;
	len = skb->len - hdr_len;
@@ -297,9 +289,9 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
	pos += hdr_len;
	pos += hdr_len;
	icv = skb_put(skb, 4);
	icv = skb_put(skb, 4);


	*pos++ = rc4key[0];
	*pos++ = *rc4key;
	*pos++ = rc4key[1];
	*pos++ = *(rc4key + 1);
	*pos++ = rc4key[2];
	*pos++ = *(rc4key + 2);
	*pos++ = (tkey->key_idx << 6) | (1 << 5) /* Ext IV included */ ;
	*pos++ = (tkey->key_idx << 6) | (1 << 5) /* Ext IV included */ ;
	*pos++ = tkey->tx_iv32 & 0xff;
	*pos++ = tkey->tx_iv32 & 0xff;
	*pos++ = (tkey->tx_iv32 >> 8) & 0xff;
	*pos++ = (tkey->tx_iv32 >> 8) & 0xff;
@@ -312,6 +304,38 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
	icv[2] = crc >> 16;
	icv[2] = crc >> 16;
	icv[3] = crc >> 24;
	icv[3] = crc >> 24;


	return rc4key;
}

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;
	struct scatterlist sg;

	if (tkey->ieee->tkip_countermeasures) {
		if (net_ratelimit()) {
			struct ieee80211_hdr_4addr *hdr =
			    (struct ieee80211_hdr_4addr *)skb->data;
			printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
			       "TX packet to " MAC_FMT "\n",
			       tkey->ieee->dev->name, MAC_ARG(hdr->addr1));
		}
		return -1;
	}

	if (skb_tailroom(skb) < 4 || skb->len < hdr_len)
		return -1;

	len = skb->len - hdr_len;
	pos = skb->data + hdr_len;

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

	crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16);
	crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16);
	sg.page = virt_to_page(pos);
	sg.page = virt_to_page(pos);
	sg.offset = offset_in_page(pos);
	sg.offset = offset_in_page(pos);
+6 −0
Original line number Original line Diff line number Diff line
@@ -1534,6 +1534,12 @@ void ieee80211_rx_mgt(struct ieee80211_device *ieee,
					      header);
					      header);
		break;
		break;


	case IEEE80211_STYPE_DEAUTH:
		printk("DEAUTH from AP\n");
		if (ieee->handle_deauth != NULL)
			ieee->handle_deauth(ieee->dev, (struct ieee80211_auth *)
					    header);
		break;
	default:
	default:
		IEEE80211_DEBUG_MGMT("received UNKNOWN (%d)\n",
		IEEE80211_DEBUG_MGMT("received UNKNOWN (%d)\n",
				     WLAN_FC_GET_STYPE(le16_to_cpu
				     WLAN_FC_GET_STYPE(le16_to_cpu
Loading