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

📄 hostap_crypt_tkip.c

📁 IEEE 802.11a/b/g linux2.4/2.6 驱动程序源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	for (k = 0; k < 4; k++) {		i = (i + 1) & 0xff;		j = (j + S[i]) & 0xff;		S_SWAP(i, j);		if ((icv[k] ^ S[(S[i] + S[j]) & 0xff]) != *pos++) {			/* ICV mismatch - drop frame */			return -1;		}	}	return 0;}#endif /* HOSTAP_USE_CRYPTO_API */static int hostap_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv){	struct hostap_tkip_data *tkey = priv;	u8 rc4key[16];	u8 keyidx, *pos;	u32 iv32;	u16 iv16;	struct hostap_ieee80211_hdr *hdr;#ifdef HOSTAP_USE_CRYPTO_API	u8 icv[4];	u32 crc;	struct scatterlist sg;	int plen;#endif /* HOSTAP_USE_CRYPTO_API */	if (skb->len < hdr_len + 8 + 4)		return -1;	hdr = (struct hostap_ieee80211_hdr *) skb->data;	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 " MACSTR "\n", MAC2STR(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 " MACSTR			       " with keyid=%d that does not have a configured"			       " key\n", MAC2STR(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=" MACSTR			       " previous TSC %08x%04x received TSC "			       "%08x%04x\n", MAC2STR(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);#ifdef HOSTAP_USE_CRYPTO_API	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) {#else /* HOSTAP_USE_CRYPTO_API */	if (hostap_wep_decrypt(rc4key, pos, skb->len - hdr_len - 12)) {#endif /* HOSTAP_USE_CRYPTO_API */		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="			       MACSTR "\n", MAC2STR(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;}#ifdef HOSTAP_USE_CRYPTO_APIstatic int michael_mic(struct hostap_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;}#else /* HOSTAP_USE_CRYPTO_API */static inline u32 rotl(u32 val, int bits){	return (val << bits) | (val >> (32 - bits));}static inline u32 rotr(u32 val, int bits){	return (val >> bits) | (val << (32 - bits));}static inline u32 xswap(u32 val){	return ((val & 0x00ff00ff) << 8) | ((val & 0xff00ff00) >> 8);}#define michael_block(l, r)	\do {				\	r ^= rotl(l, 17);	\	l += r;			\	r ^= xswap(l);		\	l += r;			\	r ^= rotl(l, 3);	\	l += r;			\	r ^= rotr(l, 2);	\	l += r;			\} while (0)static inline u32 get_le32(u8 *p){	return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);}static inline void put_le32(u8 *p, u32 v){	p[0] = v;	p[1] = v >> 8;	p[2] = v >> 16;	p[3] = v >> 24;}static int michael_mic(struct hostap_tkip_data *tkey, u8 *key, u8 *hdr,		       u8 *data, size_t data_len, u8 *mic){	u32 l, r;	int i, blocks, last;	l = get_le32(key);	r = get_le32(key + 4);	/* Michael MIC pseudo header: DA, SA, 3 x 0, Priority */	l ^= get_le32(hdr);	michael_block(l, r);	l ^= get_le32(&hdr[4]);	michael_block(l, r);	l ^= get_le32(&hdr[8]);	michael_block(l, r);	l ^= get_le32(&hdr[12]);	michael_block(l, r);	/* 32-bit blocks of data */	blocks = data_len / 4;	last = data_len % 4;	for (i = 0; i < blocks; i++) {		l ^= get_le32(&data[4 * i]);		michael_block(l, r);	}	/* Last block and padding (0x5a, 4..7 x 0) */	switch (last) {	case 0:		l ^= 0x5a;		break;	case 1:		l ^= data[4 * i] | 0x5a00;		break;	case 2:		l ^= data[4 * i] | (data[4 * i + 1] << 8) | 0x5a0000;		break;	case 3:		l ^= data[4 * i] | (data[4 * i + 1] << 8) |			(data[4 * i + 2] << 16) | 0x5a000000;		break;	}	michael_block(l, r);	/* l ^= 0; */	michael_block(l, r);	put_le32(mic, l);	put_le32(mic + 4, r);	return 0;}#endif /* HOSTAP_USE_CRYPTO_API */static void michael_mic_hdr(struct sk_buff *skb, u8 *hdr){	struct hostap_ieee80211_hdr *hdr11;	hdr11 = (struct hostap_ieee80211_hdr *) skb->data;	switch (le16_to_cpu(hdr11->frame_control) &		(WLAN_FC_FROMDS | WLAN_FC_TODS)) {	case WLAN_FC_TODS:		memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */		memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */		break;	case WLAN_FC_FROMDS:		memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */		memcpy(hdr + ETH_ALEN, hdr11->addr3, ETH_ALEN); /* SA */		break;	case WLAN_FC_FROMDS | WLAN_FC_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 hostap_michael_mic_add(struct sk_buff *skb, int hdr_len, void *priv){	struct hostap_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;}#if WIRELESS_EXT >= 18static void hostap_michael_mic_failure(struct net_device *dev,				       struct hostap_ieee80211_hdr *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);}#elif WIRELESS_EXT >= 15static void hostap_michael_mic_failure(struct net_device *dev,				       struct hostap_ieee80211_hdr *hdr,				       int keyidx){	union iwreq_data wrqu;	char buf[128];	/* TODO: needed parameters: count, keyid, key type, TSC */	sprintf(buf, "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast addr="		MACSTR ")", keyidx, hdr->addr1[0] & 0x01 ? "broad" : "uni",		MAC2STR(hdr->addr2));	memset(&wrqu, 0, sizeof(wrqu));	wrqu.data.length = strlen(buf);	wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);}#else /* WIRELESS_EXT >= 15 */static inline void hostap_michael_mic_failure(struct net_device *dev,					      struct hostap_ieee80211_hdr *hdr,					      int keyidx){}#endif /* WIRELESS_EXT >= 15 */static int hostap_michael_mic_verify(struct sk_buff *skb, int keyidx,				     int hdr_len, void *priv){	struct hostap_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 hostap_ieee80211_hdr *hdr;		hdr = (struct hostap_ieee80211_hdr *) skb->data;		printk(KERN_DEBUG "%s: Michael MIC verification failed for "		       "MSDU from " MACSTR " keyidx=%d\n",		       skb->dev ? skb->dev->name : "N/A", MAC2STR(hdr->addr2),		       keyidx);		if (skb->dev)			hostap_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 hostap_tkip_set_key(void *key, int len, u8 *seq, void *priv){	struct hostap_tkip_data *tkey = priv;	int keyidx;#ifdef HOSTAP_USE_CRYPTO_API	struct crypto_tfm *tfm = tkey->tfm_michael;	struct crypto_tfm *tfm2 = tkey->tfm_arc4;#endif /* HOSTAP_USE_CRYPTO_API */	keyidx = tkey->key_idx;	memset(tkey, 0, sizeof(*tkey));	tkey->key_idx = keyidx;#ifdef HOSTAP_USE_CRYPTO_API	tkey->tfm_michael = tfm;	tkey->tfm_arc4 = tfm2;#endif /* HOSTAP_USE_CRYPTO_API */	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 hostap_tkip_get_key(void *key, int len, u8 *seq, void *priv){	struct hostap_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 * hostap_tkip_print_stats(char *p, void *priv){	struct hostap_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 hostap_crypto_ops hostap_crypt_tkip = {	.name			= "TKIP",	.init			= hostap_tkip_init,	.deinit			= hostap_tkip_deinit,	.encrypt_mpdu		= hostap_tkip_encrypt,	.decrypt_mpdu		= hostap_tkip_decrypt,	.encrypt_msdu		= hostap_michael_mic_add,	.decrypt_msdu		= hostap_michael_mic_verify,	.set_key		= hostap_tkip_set_key,	.get_key		= hostap_tkip_get_key,	.print_stats		= hostap_tkip_print_stats,	.extra_prefix_len	= 4 + 4 /* IV + ExtIV */,	.extra_postfix_len	= 8 + 4 /* MIC + ICV */};static int __init hostap_crypto_tkip_init(void){	if (hostap_register_crypto_ops(&hostap_crypt_tkip) < 0)		return -1;	return 0;}static void __exit hostap_crypto_tkip_exit(void){	hostap_unregister_crypto_ops(&hostap_crypt_tkip);}module_init(hostap_crypto_tkip_init);module_exit(hostap_crypto_tkip_exit);

⌨️ 快捷键说明

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