⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ieee80211_crypt_tkip.c

📁 Source for the 802.11 (wireless) network stack for Linux
💻 C
📖 第 1 页 / 共 2 页
字号:
static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv){	struct ieee80211_tkip_data *tkey = priv;	u8 rc4key[16];	u8 keyidx, *pos;	u32 iv32;	u16 iv16;	struct ieee80211_hdr_4addr *hdr;	u8 icv[4];	u32 crc;	struct scatterlist sg;	int plen;	hdr = (struct ieee80211_hdr_4addr *)skb->data;	if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) {		if (net_ratelimit()) {			printk(KERN_DEBUG "TKIP countermeasures: dropped "			       "received packet from " MAC_FMT "\n",			       MAC_ARG(hdr->addr2));		}		return -1;	}	if (skb->len < hdr_len + 8 + 4)		return -1;	pos = skb->data + hdr_len;	keyidx = pos[3];	if (!(keyidx & (1 << 5))) {		if (net_ratelimit()) {			printk(KERN_DEBUG "TKIP: received packet without ExtIV"			       " flag from " MAC_FMT "\n", MAC_ARG(hdr->addr2));		}		return -2;	}	keyidx >>= 6;	if (tkey->key_idx != keyidx) {		printk(KERN_DEBUG "TKIP: RX tkey->key_idx=%d frame "		       "keyidx=%d priv=%p\n", tkey->key_idx, keyidx, priv);		return -6;	}	if (!tkey->key_set) {		if (net_ratelimit()) {			printk(KERN_DEBUG "TKIP: received packet from " MAC_FMT			       " with keyid=%d that does not have a configured"			       " key\n", MAC_ARG(hdr->addr2), keyidx);		}		return -3;	}	iv16 = (pos[0] << 8) | pos[2];	iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24);	pos += 8;	if (iv32 < tkey->rx_iv32 ||	    (iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) {		if (net_ratelimit()) {			printk(KERN_DEBUG "TKIP: replay detected: STA=" MAC_FMT			       " previous TSC %08x%04x received TSC "			       "%08x%04x\n", MAC_ARG(hdr->addr2),			       tkey->rx_iv32, tkey->rx_iv16, iv32, iv16);		}		tkey->dot11RSNAStatsTKIPReplays++;		return -4;	}	if (iv32 != tkey->rx_iv32 || !tkey->rx_phase1_done) {		tkip_mixing_phase1(tkey->rx_ttak, tkey->key, hdr->addr2, iv32);		tkey->rx_phase1_done = 1;	}	tkip_mixing_phase2(rc4key, tkey->key, tkey->rx_ttak, iv16);	plen = skb->len - hdr_len - 12;	crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16);	sg.page = virt_to_page(pos);	sg.offset = offset_in_page(pos);	sg.length = plen + 4;	crypto_cipher_decrypt(tkey->tfm_arc4, &sg, &sg, plen + 4);	crc = ~crc32_le(~0, pos, plen);	icv[0] = crc;	icv[1] = crc >> 8;	icv[2] = crc >> 16;	icv[3] = crc >> 24;	if (memcmp(icv, pos + plen, 4) != 0) {		if (iv32 != tkey->rx_iv32) {			/* Previously cached Phase1 result was already lost, so			 * it needs to be recalculated for the next packet. */			tkey->rx_phase1_done = 0;		}		if (net_ratelimit()) {			printk(KERN_DEBUG "TKIP: ICV error detected: STA="			       MAC_FMT "\n", MAC_ARG(hdr->addr2));		}		tkey->dot11RSNAStatsTKIPICVErrors++;		return -5;	}	/* Update real counters only after Michael MIC verification has	 * completed */	tkey->rx_iv32_new = iv32;	tkey->rx_iv16_new = iv16;	/* Remove IV and ICV */	memmove(skb->data + 8, skb->data, hdr_len);	skb_pull(skb, 8);	skb_trim(skb, skb->len - 4);	return keyidx;}static int michael_mic(struct ieee80211_tkip_data *tkey, u8 * key, u8 * hdr,		       u8 * data, size_t data_len, u8 * mic){	struct scatterlist sg[2];	if (tkey->tfm_michael == NULL) {		printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n");		return -1;	}	sg[0].page = virt_to_page(hdr);	sg[0].offset = offset_in_page(hdr);	sg[0].length = 16;	sg[1].page = virt_to_page(data);	sg[1].offset = offset_in_page(data);	sg[1].length = data_len;	crypto_digest_init(tkey->tfm_michael);	crypto_digest_setkey(tkey->tfm_michael, key, 8);	crypto_digest_update(tkey->tfm_michael, sg, 2);	crypto_digest_final(tkey->tfm_michael, mic);	return 0;}static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr){	struct ieee80211_hdr_4addr *hdr11;	hdr11 = (struct ieee80211_hdr_4addr *)skb->data;	switch (le16_to_cpu(hdr11->frame_ctl) &		(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {	case IEEE80211_FCTL_TODS:		memcpy(hdr, hdr11->addr3, ETH_ALEN);	/* DA */		memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN);	/* SA */		break;	case IEEE80211_FCTL_FROMDS:		memcpy(hdr, hdr11->addr1, ETH_ALEN);	/* DA */		memcpy(hdr + ETH_ALEN, hdr11->addr3, ETH_ALEN);	/* SA */		break;	case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS:		memcpy(hdr, hdr11->addr3, ETH_ALEN);	/* DA */		memcpy(hdr + ETH_ALEN, hdr11->addr4, ETH_ALEN);	/* SA */		break;	case 0:		memcpy(hdr, hdr11->addr1, ETH_ALEN);	/* DA */		memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN);	/* SA */		break;	}	hdr[12] = 0;		/* priority */	hdr[13] = hdr[14] = hdr[15] = 0;	/* reserved */}static int ieee80211_michael_mic_add(struct sk_buff *skb, int hdr_len,				     void *priv){	struct ieee80211_tkip_data *tkey = priv;	u8 *pos;	if (skb_tailroom(skb) < 8 || skb->len < hdr_len) {		printk(KERN_DEBUG "Invalid packet for Michael MIC add "		       "(tailroom=%d hdr_len=%d skb->len=%d)\n",		       skb_tailroom(skb), hdr_len, skb->len);		return -1;	}	michael_mic_hdr(skb, tkey->tx_hdr);	pos = skb_put(skb, 8);	if (michael_mic(tkey, &tkey->key[16], tkey->tx_hdr,			skb->data + hdr_len, skb->len - 8 - hdr_len, pos))		return -1;	return 0;}static void ieee80211_michael_mic_failure(struct net_device *dev,					  struct ieee80211_hdr_4addr *hdr,					  int keyidx){#if WIRELESS_EXT >= 18	union iwreq_data wrqu;	struct iw_michaelmicfailure ev;	/* TODO: needed parameters: count, keyid, key type, TSC */	memset(&ev, 0, sizeof(ev));	ev.flags = keyidx & IW_MICFAILURE_KEY_ID;	if (hdr->addr1[0] & 0x01)		ev.flags |= IW_MICFAILURE_GROUP;	else		ev.flags |= IW_MICFAILURE_PAIRWISE;	ev.src_addr.sa_family = ARPHRD_ETHER;	memcpy(ev.src_addr.sa_data, hdr->addr2, ETH_ALEN);	memset(&wrqu, 0, sizeof(wrqu));	wrqu.data.length = sizeof(ev);	wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&ev);#endif}static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx,					int hdr_len, void *priv){	struct ieee80211_tkip_data *tkey = priv;	u8 mic[8];	if (!tkey->key_set)		return -1;	michael_mic_hdr(skb, tkey->rx_hdr);	if (michael_mic(tkey, &tkey->key[24], tkey->rx_hdr,			skb->data + hdr_len, skb->len - 8 - hdr_len, mic))		return -1;	if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) {		struct ieee80211_hdr_4addr *hdr;		hdr = (struct ieee80211_hdr_4addr *)skb->data;		printk(KERN_DEBUG "%s: Michael MIC verification failed for "		       "MSDU from " MAC_FMT " keyidx=%d\n",		       skb->dev ? skb->dev->name : "N/A", MAC_ARG(hdr->addr2),		       keyidx);		if (skb->dev)			ieee80211_michael_mic_failure(skb->dev, hdr, keyidx);		tkey->dot11RSNAStatsTKIPLocalMICFailures++;		return -1;	}	/* Update TSC counters for RX now that the packet verification has	 * completed. */	tkey->rx_iv32 = tkey->rx_iv32_new;	tkey->rx_iv16 = tkey->rx_iv16_new;	skb_trim(skb, skb->len - 8);	return 0;}static int ieee80211_tkip_set_key(void *key, int len, u8 * seq, void *priv){	struct ieee80211_tkip_data *tkey = priv;	int keyidx;	struct crypto_tfm *tfm = tkey->tfm_michael;	struct crypto_tfm *tfm2 = tkey->tfm_arc4;	keyidx = tkey->key_idx;	memset(tkey, 0, sizeof(*tkey));	tkey->key_idx = keyidx;	tkey->tfm_michael = tfm;	tkey->tfm_arc4 = tfm2;	if (len == TKIP_KEY_LEN) {		memcpy(tkey->key, key, TKIP_KEY_LEN);		tkey->key_set = 1;		tkey->tx_iv16 = 1;	/* TSC is initialized to 1 */		if (seq) {			tkey->rx_iv32 = (seq[5] << 24) | (seq[4] << 16) |			    (seq[3] << 8) | seq[2];			tkey->rx_iv16 = (seq[1] << 8) | seq[0];		}	} else if (len == 0)		tkey->key_set = 0;	else		return -1;	return 0;}static int ieee80211_tkip_get_key(void *key, int len, u8 * seq, void *priv){	struct ieee80211_tkip_data *tkey = priv;	if (len < TKIP_KEY_LEN)		return -1;	if (!tkey->key_set)		return 0;	memcpy(key, tkey->key, TKIP_KEY_LEN);	if (seq) {		/* Return the sequence number of the last transmitted frame. */		u16 iv16 = tkey->tx_iv16;		u32 iv32 = tkey->tx_iv32;		if (iv16 == 0)			iv32--;		iv16--;		seq[0] = tkey->tx_iv16;		seq[1] = tkey->tx_iv16 >> 8;		seq[2] = tkey->tx_iv32;		seq[3] = tkey->tx_iv32 >> 8;		seq[4] = tkey->tx_iv32 >> 16;		seq[5] = tkey->tx_iv32 >> 24;	}	return TKIP_KEY_LEN;}static char *ieee80211_tkip_print_stats(char *p, void *priv){	struct ieee80211_tkip_data *tkip = priv;	p += sprintf(p, "key[%d] alg=TKIP key_set=%d "		     "tx_pn=%02x%02x%02x%02x%02x%02x "		     "rx_pn=%02x%02x%02x%02x%02x%02x "		     "replays=%d icv_errors=%d local_mic_failures=%d\n",		     tkip->key_idx, tkip->key_set,		     (tkip->tx_iv32 >> 24) & 0xff,		     (tkip->tx_iv32 >> 16) & 0xff,		     (tkip->tx_iv32 >> 8) & 0xff,		     tkip->tx_iv32 & 0xff,		     (tkip->tx_iv16 >> 8) & 0xff,		     tkip->tx_iv16 & 0xff,		     (tkip->rx_iv32 >> 24) & 0xff,		     (tkip->rx_iv32 >> 16) & 0xff,		     (tkip->rx_iv32 >> 8) & 0xff,		     tkip->rx_iv32 & 0xff,		     (tkip->rx_iv16 >> 8) & 0xff,		     tkip->rx_iv16 & 0xff,		     tkip->dot11RSNAStatsTKIPReplays,		     tkip->dot11RSNAStatsTKIPICVErrors,		     tkip->dot11RSNAStatsTKIPLocalMICFailures);	return p;}static struct ieee80211_crypto_ops ieee80211_crypt_tkip = {	.name = "TKIP",	.init = ieee80211_tkip_init,	.deinit = ieee80211_tkip_deinit,	.encrypt_mpdu = ieee80211_tkip_encrypt,	.decrypt_mpdu = ieee80211_tkip_decrypt,	.encrypt_msdu = ieee80211_michael_mic_add,	.decrypt_msdu = ieee80211_michael_mic_verify,	.set_key = ieee80211_tkip_set_key,	.get_key = ieee80211_tkip_get_key,	.print_stats = ieee80211_tkip_print_stats,	.extra_mpdu_prefix_len = 4 + 4,	/* IV + ExtIV */	.extra_mpdu_postfix_len = 4,	/* ICV */	.extra_msdu_postfix_len = 8,	/* MIC */	.get_flags = ieee80211_tkip_get_flags,	.set_flags = ieee80211_tkip_set_flags,	.owner = THIS_MODULE,};static int __init ieee80211_crypto_tkip_init(void){	return ieee80211_register_crypto_ops(&ieee80211_crypt_tkip);}static void __exit ieee80211_crypto_tkip_exit(void){	ieee80211_unregister_crypto_ops(&ieee80211_crypt_tkip);}module_init(ieee80211_crypto_tkip_init);module_exit(ieee80211_crypto_tkip_exit);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -