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

📄 wpa.c

📁 一个Linux下无线网卡的设置工具
💻 C
📖 第 1 页 / 共 5 页
字号:
		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;		}	}	if (left > 0) {		wpa_printf(MSG_DEBUG, "%s: ie has %u trailing bytes - ignored",			   __func__, left);	}	return 0;}/** * 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;	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) {		memcpy(pos, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN);	} else if (group_cipher == WPA_CIPHER_TKIP) {		memcpy(pos, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN);	} else if (group_cipher == WPA_CIPHER_WEP104) {		memcpy(pos, WPA_CIPHER_SUITE_WEP104, WPA_SELECTOR_LEN);	} else if (group_cipher == WPA_CIPHER_WEP40) {		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) {		memcpy(pos, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN);	} else if (pairwise_cipher == WPA_CIPHER_TKIP) {		memcpy(pos, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN);	} else if (pairwise_cipher == WPA_CIPHER_NONE) {		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) {		memcpy(pos, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X, WPA_SELECTOR_LEN);	} else if (key_mgmt == WPA_KEY_MGMT_PSK) {		memcpy(pos, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X,		       WPA_SELECTOR_LEN);	} else if (key_mgmt == WPA_KEY_MGMT_WPA_NONE) {		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(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, struct wpa_sm *sm){	u8 *pos;	struct rsn_ie_hdr *hdr;	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) {		memcpy(pos, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN);	} else if (group_cipher == WPA_CIPHER_TKIP) {		memcpy(pos, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN);	} else if (group_cipher == WPA_CIPHER_WEP104) {		memcpy(pos, RSN_CIPHER_SUITE_WEP104, RSN_SELECTOR_LEN);	} else if (group_cipher == WPA_CIPHER_WEP40) {		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) {		memcpy(pos, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN);	} else if (pairwise_cipher == WPA_CIPHER_TKIP) {		memcpy(pos, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN);	} else if (pairwise_cipher == WPA_CIPHER_NONE) {		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) {		memcpy(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X, RSN_SELECTOR_LEN);	} else if (key_mgmt == WPA_KEY_MGMT_PSK) {		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 */	*pos++ = 0;	*pos++ = 0;	if (sm->cur_pmksa) {		/* PMKID Count (2 octets, little endian) */		*pos++ = 1;		*pos++ = 0;		/* PMKID */		memcpy(pos, sm->cur_pmksa->pmkid, PMKID_LEN);		pos += PMKID_LEN;	}	hdr->len = (pos - rsn_ie) - 2;	WPA_ASSERT(pos - rsn_ie <= rsn_ie_len);	return pos - rsn_ie;}/** * 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);	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 * @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)) */static void wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len,			   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 (memcmp(addr1, addr2, ETH_ALEN) < 0) {		memcpy(data, addr1, ETH_ALEN);		memcpy(data + ETH_ALEN, addr2, ETH_ALEN);	} else {		memcpy(data, addr2, ETH_ALEN);		memcpy(data + ETH_ALEN, addr1, ETH_ALEN);	}	if (memcmp(nonce1, nonce2, 32) < 0) {		memcpy(data + 2 * ETH_ALEN, nonce1, 32);		memcpy(data + 2 * ETH_ALEN + 32, nonce2, 32);	} else {		memcpy(data + 2 * ETH_ALEN, nonce2, 32);		memcpy(data + 2 * ETH_ALEN + 32, nonce1, 32);	}	sha1_prf(pmk, pmk_len, "Pairwise key expansion", 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);		memcpy(mic, hash, MD5_MAC_LEN);	}}static void wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck,			       int ver, const u8 *dest, u16 proto,			       u8 *msg, size_t msg_len, u8 *key_mic){	if (key_mic) {		wpa_eapol_key_mic(kck, ver, msg, msg_len, key_mic);	}	wpa_hexdump(MSG_MSGDUMP, "WPA: TX EAPOL-Key", msg, msg_len);	wpa_sm_ether_send(sm, dest, proto, msg, msg_len);	eapol_sm_notify_tx_eapol_key(sm->eapol);	free(msg);}/** * wpa_sm_key_request - Send EAPOL-Key Request * @sm: Pointer to WPA state machine data from wpa_sm_init() * @error: Indicate whether this is an Michael MIC error report * @pairwise: 1 = error report for pairwise packet, 0 = for group packet * Returns: Pointer to the current network structure or %NULL on failure * * Send an EAPOL-Key Request to the current authenticator. This function is * used to request rekeying and it is usually called when a local Michael MIC * failure is detected. */void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise){	size_t rlen;	struct wpa_eapol_key *reply;	int key_info, ver;	u8 bssid[ETH_ALEN], *rbuf;	if (sm->pairwise_cipher == WPA_CIPHER_CCMP)		ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;	else		ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;	if (wpa_sm_get_bssid(sm, bssid) < 0) {		wpa_printf(MSG_WARNING, "Failed to read BSSID for EAPOL-Key "			   "request");		return;	}	rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,				  sizeof(*reply), &rlen, (void *) &reply);	if (rbuf == NULL)		return;	reply->type = sm->proto == WPA_PROTO_RSN ?		EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;	key_info = WPA_KEY_INFO_REQUEST | ver;	if (sm->ptk_set)		key_info |= WPA_KEY_INFO_MIC;	if (error)		key_info |= WPA_KEY_INFO_ERROR;	if (pairwise)		key_info |= WPA_KEY_INFO_KEY_TYPE;	WPA_PUT_BE16(reply->key_info, key_info);	WPA_PUT_BE16(reply->key_length, 0);	memcpy(reply->replay_counter, sm->request_counter,	       WPA_REPLAY_COUNTER_LEN);	inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN);	WPA_PUT_BE16(reply->key_data_length, 0);	wpa_printf(MSG_INFO, "WPA: Sending EAPOL-Key Request (error=%d "		   "pairwise=%d ptk_set=%d len=%lu)",		   error, pairwise, sm->ptk_set, (unsigned long) rlen);	wpa_eapol_key_send(sm, sm->ptk.kck, ver, bssid, ETH_P_EAPOL,			   rbuf, rlen, key_info & WPA_KEY_INFO_MIC ?			   reply->key_mic : NULL);}struct wpa_eapol_ie_parse {	const u8 *wpa_ie;	size_t wpa_ie_len;	const u8 *rsn_ie;	size_t rsn_ie_len;	const u8 *pmkid;	const u8 *gtk;	size_t gtk_len;};/** * wpa_supplicant_parse_generic - Parse EAPOL-Key Key Data Generic IEs * @pos: Pointer to the IE header * @end: Pointer to the end of the Key Data buffer * @ie: Pointer to parsed IE data * Returns: 0 on success, 1 if end mark is found, -1 on failure */static int wpa_supplicant_parse_generic(const u8 *pos, const u8 *end,					struct wpa_eapol_ie_parse *ie){	if (pos[1] == 0)		return 1;	if (pos[1] >= 6 &&	    memcmp(pos + 2, WPA_OUI_TYPE, WPA_SELECTOR_LEN) == 0 &&	    pos[2 + WPA_SELECTOR_LEN] == 1 &&	    pos[2 + WPA_SELECTOR_LEN + 1] == 0) {		ie->wpa_ie = pos;		ie->wpa_ie_len = pos[1] + 2;		return 0;	}	if (pos + 1 + RSN_SELECTOR_LEN < end &&	    pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN &&	    memcmp(pos + 2, RSN_KEY_DATA_PMKID, RSN_SELECTOR_LEN) == 0) {		ie->pmkid = pos + 2 + RSN_SELECTOR_LEN;		return 0;	}	if (pos[1] > RSN_SELECTOR_LEN + 2 &&	    memcmp(pos + 2, RSN_KEY_DATA_GROUPKEY, RSN_SELECTOR_LEN) == 0) {		ie->gtk = pos + 2 + RSN_SELECTOR_LEN;		ie->gtk_len = pos[1] - RSN_SELECTOR_LEN;	}	return 0;}/** * wpa_supplicant_parse_ies - Parse EAPOL-Key Key Data IEs * @buf: Pointer to the Key Data buffer * @len: Key Data Length * @ie: Pointer to parsed IE data * Returns: 0 on success, -1 on failure */static int wpa_supplicant_parse_ies(const u8 *buf, size_t len,				    struct wpa_eapol_ie_parse *ie){	const u8 *pos, *end;	int ret = 0;	memset(ie, 0, sizeof(*ie));	for (pos = buf, end = pos + len; pos + 1 < end; pos += 2 + pos[1]) {		if (pos + 2 + pos[1] > end) {			wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key Key Data "				   "underflow (ie=%d len=%d)", pos[0], pos[1]);			ret = -1;			break;		}		if (*pos == RSN_INFO_ELEM) {			ie->rsn_ie = pos;			ie->rsn_ie_len = pos[1] + 2;		} else if (*pos == GENERIC_INFO_ELEM) {			ret = wpa_supplicant_parse_generic(pos, end, ie);			if (ret < 0)				break;			if (ret > 0) {				ret = 0;				break;			}		} else {			wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized EAPOL-Key "

⌨️ 快捷键说明

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