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

📄 ieee80211_crypt_tkip.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
}/* * deal with seq counter wrapping correctly. * refer to timer_after() for jiffies wrapping handling */static inline int tkip_replay_check(u32 iv32_n, u16 iv16_n,				    u32 iv32_o, u16 iv16_o){	if ((s32)iv32_n - (s32)iv32_o < 0 ||	    (iv32_n == iv32_o && iv16_n <= iv16_o))		return 1;	return 0;}static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv){	struct ieee80211_tkip_data *tkey = priv;	struct blkcipher_desc desc = { .tfm = tkey->rx_tfm_arc4 };	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;	DECLARE_MAC_BUF(mac);	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 %s\n",			       print_mac(mac, 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 %s\n", print_mac(mac, 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 %s"			       " with keyid=%d that does not have a configured"			       " key\n", print_mac(mac, 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 (tkip_replay_check(iv32, iv16, tkey->rx_iv32, tkey->rx_iv16)) {		if (ieee80211_ratelimit_debug(IEEE80211_DL_DROP)) {			IEEE80211_DEBUG_DROP("TKIP: replay detected: STA=%s"			       " previous TSC %08x%04x received TSC "			       "%08x%04x\n", print_mac(mac, 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_blkcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16);	sg_init_one(&sg, pos, plen + 4);	if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) {		if (net_ratelimit()) {			printk(KERN_DEBUG ": TKIP: failed to decrypt "			       "received packet from %s\n",			       print_mac(mac, hdr->addr2));		}		return -7;	}	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 (ieee80211_ratelimit_debug(IEEE80211_DL_DROP)) {			IEEE80211_DEBUG_DROP("TKIP: ICV error detected: STA="			       "%s\n", print_mac(mac, 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 crypto_hash *tfm_michael, u8 * key, u8 * hdr,		       u8 * data, size_t data_len, u8 * mic){	struct hash_desc desc;	struct scatterlist sg[2];	if (tfm_michael == NULL) {		printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n");		return -1;	}	sg_init_table(sg, 2);	sg_set_buf(&sg[0], hdr, 16);	sg_set_buf(&sg[1], data, data_len);	if (crypto_hash_setkey(tfm_michael, key, 8))		return -1;	desc.tfm = tfm_michael;	desc.flags = 0;	return crypto_hash_digest(&desc, sg, data_len + 16, mic);}static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr){	struct ieee80211_hdr_4addr *hdr11;	u16 stype;	hdr11 = (struct ieee80211_hdr_4addr *)skb->data;	stype  = WLAN_FC_GET_STYPE(le16_to_cpu(hdr11->frame_ctl));	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;	}	if (stype & IEEE80211_STYPE_QOS_DATA) {		const struct ieee80211_hdr_3addrqos *qoshdr =			(struct ieee80211_hdr_3addrqos *)skb->data;		hdr[12] = le16_to_cpu(qoshdr->qos_ctl) & IEEE80211_QCTL_TID;	} else		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->tx_tfm_michael, &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){	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);}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];	DECLARE_MAC_BUF(mac);	if (!tkey->key_set)		return -1;	michael_mic_hdr(skb, tkey->rx_hdr);	if (michael_mic(tkey->rx_tfm_michael, &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 %s keyidx=%d\n",		       skb->dev ? skb->dev->name : "N/A", print_mac(mac, 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_hash *tfm = tkey->tx_tfm_michael;	struct crypto_blkcipher *tfm2 = tkey->tx_tfm_arc4;	struct crypto_hash *tfm3 = tkey->rx_tfm_michael;	struct crypto_blkcipher *tfm4 = tkey->rx_tfm_arc4;	keyidx = tkey->key_idx;	memset(tkey, 0, sizeof(*tkey));	tkey->key_idx = keyidx;	tkey->tx_tfm_michael = tfm;	tkey->tx_tfm_arc4 = tfm2;	tkey->rx_tfm_michael = tfm3;	tkey->rx_tfm_arc4 = tfm4;	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,	.build_iv = ieee80211_tkip_hdr,	.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 + -