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

📄 wpa.c

📁 WLAN无线网络管理的最新程序
💻 C
📖 第 1 页 / 共 5 页
字号:
	return 0;}static int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,				struct wpa_ie_data *data){#ifndef CONFIG_NO_WPA2	const struct rsn_ie_hdr *hdr;	const u8 *pos;	int left;	int i, count;	data->proto = WPA_PROTO_RSN;	data->pairwise_cipher = WPA_CIPHER_CCMP;	data->group_cipher = WPA_CIPHER_CCMP;	data->key_mgmt = WPA_KEY_MGMT_IEEE8021X;	data->capabilities = 0;	data->pmkid = NULL;	data->num_pmkid = 0;#ifdef CONFIG_IEEE80211W	data->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;#else /* CONFIG_IEEE80211W */	data->mgmt_group_cipher = 0;#endif /* CONFIG_IEEE80211W */	if (rsn_ie_len == 0) {		/* No RSN IE - fail silently */		return -1;	}	if (rsn_ie_len < sizeof(struct rsn_ie_hdr)) {		wpa_printf(MSG_DEBUG, "%s: ie len too short %lu",			   __func__, (unsigned long) rsn_ie_len);		return -1;	}	hdr = (const struct rsn_ie_hdr *) rsn_ie;	if (hdr->elem_id != RSN_INFO_ELEM ||	    hdr->len != rsn_ie_len - 2 ||	    WPA_GET_LE16(hdr->version) != RSN_VERSION) {		wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version",			   __func__);		return -1;	}	pos = (const u8 *) (hdr + 1);	left = rsn_ie_len - sizeof(*hdr);	if (left >= RSN_SELECTOR_LEN) {		data->group_cipher = rsn_selector_to_bitfield(pos);#ifdef CONFIG_IEEE80211W		if (data->group_cipher == WPA_CIPHER_AES_128_CMAC) {			wpa_printf(MSG_DEBUG, "%s: AES-128-CMAC used as group "				   "cipher", __func__);			return -1;		}#endif /* CONFIG_IEEE80211W */		pos += RSN_SELECTOR_LEN;		left -= RSN_SELECTOR_LEN;	} else if (left > 0) {		wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much",			   __func__, left);		return -1;	}	if (left >= 2) {		data->pairwise_cipher = 0;		count = WPA_GET_LE16(pos);		pos += 2;		left -= 2;		if (count == 0 || left < count * RSN_SELECTOR_LEN) {			wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), "				   "count %u left %u", __func__, count, left);			return -1;		}		for (i = 0; i < count; i++) {			data->pairwise_cipher |= rsn_selector_to_bitfield(pos);			pos += RSN_SELECTOR_LEN;			left -= RSN_SELECTOR_LEN;		}#ifdef CONFIG_IEEE80211W		if (data->pairwise_cipher & WPA_CIPHER_AES_128_CMAC) {			wpa_printf(MSG_DEBUG, "%s: AES-128-CMAC used as "				   "pairwise cipher", __func__);			return -1;		}#endif /* CONFIG_IEEE80211W */	} else if (left == 1) {		wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)",			   __func__);		return -1;	}	if (left >= 2) {		data->key_mgmt = 0;		count = WPA_GET_LE16(pos);		pos += 2;		left -= 2;		if (count == 0 || left < count * RSN_SELECTOR_LEN) {			wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), "				   "count %u left %u", __func__, count, left);			return -1;		}		for (i = 0; i < count; i++) {			data->key_mgmt |= rsn_key_mgmt_to_bitfield(pos);			pos += RSN_SELECTOR_LEN;			left -= RSN_SELECTOR_LEN;		}	} else if (left == 1) {		wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)",			   __func__);		return -1;	}	if (left >= 2) {		data->capabilities = WPA_GET_LE16(pos);		pos += 2;		left -= 2;	}	if (left >= 2) {		data->num_pmkid = WPA_GET_LE16(pos);		pos += 2;		left -= 2;		if (left < data->num_pmkid * PMKID_LEN) {			wpa_printf(MSG_DEBUG, "%s: PMKID underflow "				   "(num_pmkid=%d left=%d)",				   __func__, data->num_pmkid, left);			data->num_pmkid = 0;		} else {			data->pmkid = pos;			pos += data->num_pmkid * PMKID_LEN;			left -= data->num_pmkid * PMKID_LEN;		}	}#ifdef CONFIG_IEEE80211W	if (left >= 4) {		data->mgmt_group_cipher = rsn_selector_to_bitfield(pos);		if (data->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) {			wpa_printf(MSG_DEBUG, "%s: Unsupported management "				   "group cipher 0x%x", __func__,				   data->mgmt_group_cipher);			return -1;		}		pos += RSN_SELECTOR_LEN;		left -= RSN_SELECTOR_LEN;	}#endif /* CONFIG_IEEE80211W */	if (left > 0) {		wpa_printf(MSG_DEBUG, "%s: ie has %u trailing bytes - ignored",			   __func__, left);	}	return 0;#else /* CONFIG_NO_WPA2 */	return -1;#endif /* CONFIG_NO_WPA2 */}/** * wpa_parse_wpa_ie - Parse WPA/RSN IE * @wpa_ie: Pointer to WPA or RSN IE * @wpa_ie_len: Length of the WPA/RSN IE * @data: Pointer to data area for parsing results * Returns: 0 on success, -1 on failure * * Parse the contents of WPA or RSN IE and write the parsed data into data. */int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len,		     struct wpa_ie_data *data){	if (wpa_ie_len >= 1 && wpa_ie[0] == RSN_INFO_ELEM)		return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data);	else		return wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, data);}static int wpa_gen_wpa_ie_wpa(u8 *wpa_ie, size_t wpa_ie_len,			      int pairwise_cipher, int group_cipher,			      int key_mgmt){	u8 *pos;	struct wpa_ie_hdr *hdr;	if (wpa_ie_len < sizeof(*hdr) + WPA_SELECTOR_LEN +	    2 + WPA_SELECTOR_LEN + 2 + WPA_SELECTOR_LEN)		return -1;	hdr = (struct wpa_ie_hdr *) wpa_ie;	hdr->elem_id = GENERIC_INFO_ELEM;	os_memcpy(hdr->oui, WPA_OUI_TYPE, WPA_SELECTOR_LEN);	WPA_PUT_LE16(hdr->version, WPA_VERSION);	pos = (u8 *) (hdr + 1);	if (group_cipher == WPA_CIPHER_CCMP) {		os_memcpy(pos, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN);	} else if (group_cipher == WPA_CIPHER_TKIP) {		os_memcpy(pos, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN);	} else if (group_cipher == WPA_CIPHER_WEP104) {		os_memcpy(pos, WPA_CIPHER_SUITE_WEP104, WPA_SELECTOR_LEN);	} else if (group_cipher == WPA_CIPHER_WEP40) {		os_memcpy(pos, WPA_CIPHER_SUITE_WEP40, WPA_SELECTOR_LEN);	} else {		wpa_printf(MSG_WARNING, "Invalid group cipher (%d).",			   group_cipher);		return -1;	}	pos += WPA_SELECTOR_LEN;	*pos++ = 1;	*pos++ = 0;	if (pairwise_cipher == WPA_CIPHER_CCMP) {		os_memcpy(pos, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN);	} else if (pairwise_cipher == WPA_CIPHER_TKIP) {		os_memcpy(pos, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN);	} else if (pairwise_cipher == WPA_CIPHER_NONE) {		os_memcpy(pos, WPA_CIPHER_SUITE_NONE, WPA_SELECTOR_LEN);	} else {		wpa_printf(MSG_WARNING, "Invalid pairwise cipher (%d).",			   pairwise_cipher);		return -1;	}	pos += WPA_SELECTOR_LEN;	*pos++ = 1;	*pos++ = 0;	if (key_mgmt == WPA_KEY_MGMT_IEEE8021X) {		os_memcpy(pos, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X,			  WPA_SELECTOR_LEN);	} else if (key_mgmt == WPA_KEY_MGMT_PSK) {		os_memcpy(pos, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X,			  WPA_SELECTOR_LEN);	} else if (key_mgmt == WPA_KEY_MGMT_WPA_NONE) {		os_memcpy(pos, WPA_AUTH_KEY_MGMT_NONE, WPA_SELECTOR_LEN);	} else {		wpa_printf(MSG_WARNING, "Invalid key management type (%d).",			   key_mgmt);		return -1;	}	pos += WPA_SELECTOR_LEN;	/* WPA Capabilities; use defaults, so no need to include it */	hdr->len = (pos - wpa_ie) - 2;	WPA_ASSERT((size_t) (pos - wpa_ie) <= wpa_ie_len);	return pos - wpa_ie;}static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len,			      int pairwise_cipher, int group_cipher,			      int key_mgmt, int mgmt_group_cipher,			      struct wpa_sm *sm){#ifndef CONFIG_NO_WPA2	u8 *pos;	struct rsn_ie_hdr *hdr;	u16 capab;	if (rsn_ie_len < sizeof(*hdr) + RSN_SELECTOR_LEN +	    2 + RSN_SELECTOR_LEN + 2 + RSN_SELECTOR_LEN + 2 +	    (sm->cur_pmksa ? 2 + PMKID_LEN : 0))		return -1;	hdr = (struct rsn_ie_hdr *) rsn_ie;	hdr->elem_id = RSN_INFO_ELEM;	WPA_PUT_LE16(hdr->version, RSN_VERSION);	pos = (u8 *) (hdr + 1);	if (group_cipher == WPA_CIPHER_CCMP) {		os_memcpy(pos, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN);	} else if (group_cipher == WPA_CIPHER_TKIP) {		os_memcpy(pos, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN);	} else if (group_cipher == WPA_CIPHER_WEP104) {		os_memcpy(pos, RSN_CIPHER_SUITE_WEP104, RSN_SELECTOR_LEN);	} else if (group_cipher == WPA_CIPHER_WEP40) {		os_memcpy(pos, RSN_CIPHER_SUITE_WEP40, RSN_SELECTOR_LEN);	} else {		wpa_printf(MSG_WARNING, "Invalid group cipher (%d).",			   group_cipher);		return -1;	}	pos += RSN_SELECTOR_LEN;	*pos++ = 1;	*pos++ = 0;	if (pairwise_cipher == WPA_CIPHER_CCMP) {		os_memcpy(pos, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN);	} else if (pairwise_cipher == WPA_CIPHER_TKIP) {		os_memcpy(pos, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN);	} else if (pairwise_cipher == WPA_CIPHER_NONE) {		os_memcpy(pos, RSN_CIPHER_SUITE_NONE, RSN_SELECTOR_LEN);	} else {		wpa_printf(MSG_WARNING, "Invalid pairwise cipher (%d).",			   pairwise_cipher);		return -1;	}	pos += RSN_SELECTOR_LEN;	*pos++ = 1;	*pos++ = 0;	if (key_mgmt == WPA_KEY_MGMT_IEEE8021X) {		os_memcpy(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X,			  RSN_SELECTOR_LEN);	} else if (key_mgmt == WPA_KEY_MGMT_PSK) {		os_memcpy(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X,			  RSN_SELECTOR_LEN);	} else {		wpa_printf(MSG_WARNING, "Invalid key management type (%d).",			   key_mgmt);		return -1;	}	pos += RSN_SELECTOR_LEN;	/* RSN Capabilities */	capab = 0;#ifdef CONFIG_IEEE80211W	if (mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC)		capab |= WPA_CAPABILITY_MGMT_FRAME_PROTECTION;#endif /* CONFIG_IEEE80211W */	WPA_PUT_LE16(pos, capab);	pos += 2;	if (sm->cur_pmksa) {		/* PMKID Count (2 octets, little endian) */		*pos++ = 1;		*pos++ = 0;		/* PMKID */		os_memcpy(pos, sm->cur_pmksa->pmkid, PMKID_LEN);		pos += PMKID_LEN;	}#ifdef CONFIG_IEEE80211W	if (mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) {		if (!sm->cur_pmksa) {			/* PMKID Count */			WPA_PUT_LE16(pos, 0);			pos += 2;			/* Management Group Cipher Suite */			memcpy(pos, RSN_CIPHER_SUITE_AES_128_CMAC,			       RSN_SELECTOR_LEN);			pos += RSN_SELECTOR_LEN;		}	}#endif /* CONFIG_IEEE80211W */	hdr->len = (pos - rsn_ie) - 2;	WPA_ASSERT((size_t) (pos - rsn_ie) <= rsn_ie_len);	return pos - rsn_ie;#else /* CONFIG_NO_WPA2 */	return -1;#endif /* CONFIG_NO_WPA2 */}/** * wpa_gen_wpa_ie - Generate WPA/RSN IE based on current security policy * @sm: Pointer to WPA state machine data from wpa_sm_init() * @wpa_ie: Pointer to memory area for the generated WPA/RSN IE * @wpa_ie_len: Maximum length of the generated WPA/RSN IE * Returns: Length of the generated WPA/RSN IE or -1 on failure */static int wpa_gen_wpa_ie(struct wpa_sm *sm, u8 *wpa_ie, size_t wpa_ie_len){	if (sm->proto == WPA_PROTO_RSN)		return wpa_gen_wpa_ie_rsn(wpa_ie, wpa_ie_len,					  sm->pairwise_cipher,					  sm->group_cipher,					  sm->key_mgmt, sm->mgmt_group_cipher,					  sm);	else		return wpa_gen_wpa_ie_wpa(wpa_ie, wpa_ie_len,					  sm->pairwise_cipher,					  sm->group_cipher,					  sm->key_mgmt);}/** * wpa_pmk_to_ptk - Calculate PTK from PMK, addresses, and nonces * @pmk: Pairwise master key * @pmk_len: Length of PMK * @label: Label to use in derivation * @addr1: AA or SA * @addr2: SA or AA * @nonce1: ANonce or SNonce * @nonce2: SNonce or ANonce * @ptk: Buffer for pairwise transient key * @ptk_len: Length of PTK * * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy * PTK = PRF-X(PMK, "Pairwise key expansion", *             Min(AA, SA) || Max(AA, SA) || *             Min(ANonce, SNonce) || Max(ANonce, SNonce)) * * STK = PRF-X(SMK, "Peer key expansion", *             Min(MAC_I, MAC_P) || Max(MAC_I, MAC_P) || *             Min(INonce, PNonce) || Max(INonce, PNonce)) */static void wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len,			   const char *label,			   const u8 *addr1, const u8 *addr2,			   const u8 *nonce1, const u8 *nonce2,			   u8 *ptk, size_t ptk_len){	u8 data[2 * ETH_ALEN + 2 * 32];	if (os_memcmp(addr1, addr2, ETH_ALEN) < 0) {		os_memcpy(data, addr1, ETH_ALEN);		os_memcpy(data + ETH_ALEN, addr2, ETH_ALEN);	} else {		os_memcpy(data, addr2, ETH_ALEN);		os_memcpy(data + ETH_ALEN, addr1, ETH_ALEN);	}	if (os_memcmp(nonce1, nonce2, 32) < 0) {		os_memcpy(data + 2 * ETH_ALEN, nonce1, 32);		os_memcpy(data + 2 * ETH_ALEN + 32, nonce2, 32);	} else {		os_memcpy(data + 2 * ETH_ALEN, nonce2, 32);		os_memcpy(data + 2 * ETH_ALEN + 32, nonce1, 32);	}	sha1_prf(pmk, pmk_len, label, data, sizeof(data), ptk, ptk_len);	wpa_hexdump_key(MSG_DEBUG, "WPA: PMK", pmk, pmk_len);	wpa_hexdump_key(MSG_DEBUG, "WPA: PTK", ptk, ptk_len);}/** * wpa_eapol_key_mic - Calculate EAPOL-Key MIC * @key: EAPOL-Key Key Confirmation Key (KCK) * @ver: Key descriptor version (WPA_KEY_INFO_TYPE_*) * @buf: Pointer to the beginning of the EAPOL header (version field) * @len: Length of the EAPOL frame (from EAPOL header to the end of the frame) * @mic: Pointer to the buffer to which the EAPOL-Key MIC is written * * Calculate EAPOL-Key MIC for an EAPOL-Key packet. The EAPOL-Key MIC field has * to be cleared (all zeroes) when calling this function. * * Note: 'IEEE Std 802.11i-2004 - 8.5.2 EAPOL-Key frames' has an error in the * description of the Key MIC calculation. It includes packet data from the * beginning of the EAPOL-Key header, not EAPOL header. This incorrect change * happened during final editing of the standard and the correct behavior is * defined in the last draft (IEEE 802.11i/D10). */static void wpa_eapol_key_mic(const u8 *key, int ver,			      const u8 *buf, size_t len, u8 *mic){	if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) {		hmac_md5(key, 16, buf, len, mic);	} else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {		u8 hash[SHA1_MAC_LEN];		hmac_sha1(key, 16, buf, len, hash);		os_memcpy(mic, hash, MD5_MAC_LEN);

⌨️ 快捷键说明

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