diff options
| -rw-r--r-- | include/net/ieee80211_crypt.h | 3 | ||||
| -rw-r--r-- | net/ieee80211/ieee80211_crypt_ccmp.c | 8 | ||||
| -rw-r--r-- | net/ieee80211/ieee80211_crypt_tkip.c | 53 | ||||
| -rw-r--r-- | net/ieee80211/ieee80211_crypt_wep.c | 5 | ||||
| -rw-r--r-- | net/ieee80211/ieee80211_tx.c | 4 | 
5 files changed, 41 insertions, 32 deletions
diff --git a/include/net/ieee80211_crypt.h b/include/net/ieee80211_crypt.h index cd82c3e998e..eb476414fd7 100644 --- a/include/net/ieee80211_crypt.h +++ b/include/net/ieee80211_crypt.h @@ -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 diff --git a/net/ieee80211/ieee80211_crypt_ccmp.c b/net/ieee80211/ieee80211_crypt_ccmp.c index 47022172850..097bcea2129 100644 --- a/net/ieee80211/ieee80211_crypt_ccmp.c +++ b/net/ieee80211/ieee80211_crypt_ccmp.c @@ -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; diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/ieee80211/ieee80211_crypt_tkip.c index de56a47edb0..93def94c1b3 100644 --- a/net/ieee80211/ieee80211_crypt_tkip.c +++ b/net/ieee80211/ieee80211_crypt_tkip.c @@ -270,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); @@ -308,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));  		} @@ -342,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;  } @@ -378,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));  		} @@ -694,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, diff --git a/net/ieee80211/ieee80211_crypt_wep.c b/net/ieee80211/ieee80211_crypt_wep.c index f8dca31be5d..649e581fa56 100644 --- a/net/ieee80211/ieee80211_crypt_wep.c +++ b/net/ieee80211/ieee80211_crypt_wep.c @@ -76,7 +76,8 @@ static void prism2_wep_deinit(void *priv)  }  /* 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, void *priv) +static int prism2_wep_build_iv(struct sk_buff *skb, int hdr_len, +			       u8 *key, int keylen, void *priv)  {  	struct prism2_wep_data *wep = priv;  	u32 klen, len; @@ -131,7 +132,7 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)  		return -1;  	/* add the IV to the frame */ -	if (prism2_wep_build_iv(skb, hdr_len, priv)) +	if (prism2_wep_build_iv(skb, hdr_len, NULL, 0, priv))  		return -1;  	/* Copy the IV into the first 3 bytes of the key */ diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c index 0949803b9c7..8b4332f5339 100644 --- a/net/ieee80211/ieee80211_tx.c +++ b/net/ieee80211/ieee80211_tx.c @@ -470,7 +470,9 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)  			atomic_inc(&crypt->refcnt);  			if (crypt->ops->build_iv)  				crypt->ops->build_iv(skb_frag, hdr_len, -						     crypt->priv); +				      ieee->sec.keys[ieee->sec.active_key], +				      ieee->sec.key_sizes[ieee->sec.active_key], +				      crypt->priv);  			atomic_dec(&crypt->refcnt);  		}  |