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

📄 wpa.c

📁 最新的Host AP 新添加了许多pcmcia 的驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * WPA Supplicant - WPA state machine and EAPOL-Key processing * Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */#include "includes.h"#include "common.h"#include "rc4.h"#include "aes_wrap.h"#include "wpa.h"#include "eloop.h"#include "eapol_supp/eapol_supp_sm.h"#include "preauth.h"#include "pmksa_cache.h"#include "wpa_i.h"#include "wpa_ie.h"#include "peerkey.h"#include "ieee802_11_defs.h"/** * wpa_cipher_txt - Convert cipher suite to a text string * @cipher: Cipher suite (WPA_CIPHER_* enum) * Returns: Pointer to a text string of the cipher suite name */static const char * wpa_cipher_txt(int cipher){	switch (cipher) {	case WPA_CIPHER_NONE:		return "NONE";	case WPA_CIPHER_WEP40:		return "WEP-40";	case WPA_CIPHER_WEP104:		return "WEP-104";	case WPA_CIPHER_TKIP:		return "TKIP";	case WPA_CIPHER_CCMP:		return "CCMP";	default:		return "UNKNOWN";	}}/** * wpa_key_mgmt_txt - Convert key management suite to a text string * @key_mgmt: Key management suite (WPA_KEY_MGMT_* enum) * @proto: WPA/WPA2 version (WPA_PROTO_*) * Returns: Pointer to a text string of the key management suite name */static const char * wpa_key_mgmt_txt(int key_mgmt, int proto){	switch (key_mgmt) {	case WPA_KEY_MGMT_IEEE8021X:		return proto == WPA_PROTO_RSN ?			"WPA2/IEEE 802.1X/EAP" : "WPA/IEEE 802.1X/EAP";	case WPA_KEY_MGMT_PSK:		return proto == WPA_PROTO_RSN ?			"WPA2-PSK" : "WPA-PSK";	case WPA_KEY_MGMT_NONE:		return "NONE";	case WPA_KEY_MGMT_IEEE8021X_NO_WPA:		return "IEEE 802.1X (no WPA)";#ifdef CONFIG_IEEE80211R	case WPA_KEY_MGMT_FT_IEEE8021X:		return "FT-EAP";	case WPA_KEY_MGMT_FT_PSK:		return "FT-PSK";#endif /* CONFIG_IEEE80211R */#ifdef CONFIG_IEEE80211W	case WPA_KEY_MGMT_IEEE8021X_SHA256:		return "WPA2-EAP-SHA256";	case WPA_KEY_MGMT_PSK_SHA256:		return "WPA2-PSK-SHA256";#endif /* CONFIG_IEEE80211W */	default:		return "UNKNOWN";	}}/** * wpa_eapol_key_send - Send WPA/RSN EAPOL-Key message * @sm: Pointer to WPA state machine data from wpa_sm_init() * @kck: Key Confirmation Key (KCK, part of PTK) * @ver: Version field from Key Info * @dest: Destination address for the frame * @proto: Ethertype (usually ETH_P_EAPOL) * @msg: EAPOL-Key message * @msg_len: Length of message * @key_mic: Pointer to the buffer to which the EAPOL-Key MIC is written */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 (is_zero_ether_addr(dest) && is_zero_ether_addr(sm->bssid)) {		/*		 * Association event was not yet received; try to fetch		 * BSSID from the driver.		 */		if (wpa_sm_get_bssid(sm, sm->bssid) < 0) {			wpa_printf(MSG_DEBUG, "WPA: Failed to read BSSID for "				   "EAPOL-Key destination address");		} else {			dest = sm->bssid;			wpa_printf(MSG_DEBUG, "WPA: Use BSSID (" MACSTR				   ") as the destination for EAPOL-Key",				   MAC2STR(dest));		}	}	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);	os_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 * * 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 (wpa_key_mgmt_ft(sm->key_mgmt) || wpa_key_mgmt_sha256(sm->key_mgmt))		ver = WPA_KEY_INFO_TYPE_AES_128_CMAC;	else 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);	os_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);}static int wpa_supplicant_get_pmk(struct wpa_sm *sm,				  const unsigned char *src_addr,				  const u8 *pmkid){	int abort_cached = 0;	if (pmkid && !sm->cur_pmksa) {		/* When using drivers that generate RSN IE, wpa_supplicant may		 * not have enough time to get the association information		 * event before receiving this 1/4 message, so try to find a		 * matching PMKSA cache entry here. */		sm->cur_pmksa = pmksa_cache_get(sm->pmksa, src_addr, pmkid);		if (sm->cur_pmksa) {			wpa_printf(MSG_DEBUG, "RSN: found matching PMKID from "				   "PMKSA cache");		} else {			wpa_printf(MSG_DEBUG, "RSN: no matching PMKID found");			abort_cached = 1;		}	}	if (pmkid && sm->cur_pmksa &&	    os_memcmp(pmkid, sm->cur_pmksa->pmkid, PMKID_LEN) == 0) {		wpa_hexdump(MSG_DEBUG, "RSN: matched PMKID", pmkid, PMKID_LEN);		wpa_sm_set_pmk_from_pmksa(sm);		wpa_hexdump_key(MSG_DEBUG, "RSN: PMK from PMKSA cache",				sm->pmk, sm->pmk_len);		eapol_sm_notify_cached(sm->eapol);#ifdef CONFIG_IEEE80211R		sm->xxkey_len = 0;#endif /* CONFIG_IEEE80211R */	} else if (wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt) && sm->eapol) {		int res, pmk_len;		pmk_len = PMK_LEN;		res = eapol_sm_get_key(sm->eapol, sm->pmk, PMK_LEN);		if (res) {			/*			 * EAP-LEAP is an exception from other EAP methods: it			 * uses only 16-byte PMK.			 */			res = eapol_sm_get_key(sm->eapol, sm->pmk, 16);			pmk_len = 16;		} else {#ifdef CONFIG_IEEE80211R			u8 buf[2 * PMK_LEN];			if (eapol_sm_get_key(sm->eapol, buf, 2 * PMK_LEN) == 0)			{				os_memcpy(sm->xxkey, buf + PMK_LEN, PMK_LEN);				sm->xxkey_len = PMK_LEN;				os_memset(buf, 0, sizeof(buf));			}#endif /* CONFIG_IEEE80211R */		}		if (res == 0) {			wpa_hexdump_key(MSG_DEBUG, "WPA: PMK from EAPOL state "					"machines", sm->pmk, pmk_len);			sm->pmk_len = pmk_len;			pmksa_cache_add(sm->pmksa, sm->pmk, pmk_len, src_addr,					sm->own_addr, sm->network_ctx,					sm->key_mgmt);			if (!sm->cur_pmksa && pmkid &&			    pmksa_cache_get(sm->pmksa, src_addr, pmkid)) {				wpa_printf(MSG_DEBUG, "RSN: the new PMK "					   "matches with the PMKID");				abort_cached = 0;			}		} else {			wpa_msg(sm->ctx->ctx, MSG_WARNING,				"WPA: Failed to get master session key from "				"EAPOL state machines");			wpa_msg(sm->ctx->ctx, MSG_WARNING,				"WPA: Key handshake aborted");			if (sm->cur_pmksa) {				wpa_printf(MSG_DEBUG, "RSN: Cancelled PMKSA "					   "caching attempt");				sm->cur_pmksa = NULL;				abort_cached = 1;			} else if (!abort_cached) {				return -1;			}		}	}	if (abort_cached && wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt)) {		/* Send EAPOL-Start to trigger full EAP authentication. */		u8 *buf;		size_t buflen;		wpa_printf(MSG_DEBUG, "RSN: no PMKSA entry found - trigger "			   "full EAP authentication");		buf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_START,					 NULL, 0, &buflen, NULL);		if (buf) {			wpa_sm_ether_send(sm, sm->bssid, ETH_P_EAPOL,					  buf, buflen);			os_free(buf);		}		return -1;	}	return 0;}/** * wpa_supplicant_send_2_of_4 - Send message 2 of WPA/RSN 4-Way Handshake * @sm: Pointer to WPA state machine data from wpa_sm_init() * @dst: Destination address for the frame * @key: Pointer to the EAPOL-Key frame header * @ver: Version bits from EAPOL-Key Key Info * @nonce: Nonce value for the EAPOL-Key frame * @wpa_ie: WPA/RSN IE * @wpa_ie_len: Length of the WPA/RSN IE * @ptk: PTK to use for keyed hash and encryption * Returns: 0 on success, -1 on failure */int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,			       const struct wpa_eapol_key *key,			       int ver, const u8 *nonce,			       const u8 *wpa_ie, size_t wpa_ie_len,			       struct wpa_ptk *ptk){	size_t rlen;	struct wpa_eapol_key *reply;	u8 *rbuf;	if (wpa_ie == NULL) {		wpa_printf(MSG_WARNING, "WPA: No wpa_ie set - cannot "			   "generate msg 2/4");		return -1;	}	wpa_hexdump(MSG_DEBUG, "WPA: WPA IE for msg 2/4", wpa_ie, wpa_ie_len);	rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY,				  NULL, sizeof(*reply) + wpa_ie_len,				  &rlen, (void *) &reply);	if (rbuf == NULL)		return -1;	reply->type = sm->proto == WPA_PROTO_RSN ?		EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;	WPA_PUT_BE16(reply->key_info,		     ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_MIC);	if (sm->proto == WPA_PROTO_RSN)		WPA_PUT_BE16(reply->key_length, 0);	else		os_memcpy(reply->key_length, key->key_length, 2);	os_memcpy(reply->replay_counter, key->replay_counter,		  WPA_REPLAY_COUNTER_LEN);	WPA_PUT_BE16(reply->key_data_length, wpa_ie_len);	os_memcpy(reply + 1, wpa_ie, wpa_ie_len);	os_memcpy(reply->key_nonce, nonce, WPA_NONCE_LEN);	wpa_printf(MSG_DEBUG, "WPA: Sending EAPOL-Key 2/4");	wpa_eapol_key_send(sm, ptk->kck, ver, dst, ETH_P_EAPOL,			   rbuf, rlen, reply->key_mic);	return 0;}static int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr,			  const struct wpa_eapol_key *key,			  struct wpa_ptk *ptk){#ifdef CONFIG_IEEE80211R	if (wpa_key_mgmt_ft(sm->key_mgmt))		return wpa_derive_ptk_ft(sm, src_addr, key, ptk);#endif /* CONFIG_IEEE80211R */	wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion",		       sm->own_addr, sm->bssid, sm->snonce, key->key_nonce,		       (u8 *) ptk, sizeof(*ptk),		       wpa_key_mgmt_sha256(sm->key_mgmt));	return 0;}static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm,					  const unsigned char *src_addr,					  const struct wpa_eapol_key *key,					  u16 ver){	struct wpa_eapol_ie_parse ie;	struct wpa_ptk *ptk;	u8 buf[8];	if (wpa_sm_get_network_ctx(sm) == NULL) {		wpa_printf(MSG_WARNING, "WPA: No SSID info found (msg 1 of "			   "4).");		return;	}	wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE);	wpa_printf(MSG_DEBUG, "WPA: RX message 1 of 4-Way Handshake from "		   MACSTR " (ver=%d)", MAC2STR(src_addr), ver);	os_memset(&ie, 0, sizeof(ie));#ifndef CONFIG_NO_WPA2	if (sm->proto == WPA_PROTO_RSN) {		/* RSN: msg 1/4 should contain PMKID for the selected PMK */		const u8 *_buf = (const u8 *) (key + 1);		size_t len = WPA_GET_BE16(key->key_data_length);		wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data", _buf, len);		wpa_supplicant_parse_ies(_buf, len, &ie);		if (ie.pmkid) {			wpa_hexdump(MSG_DEBUG, "RSN: PMKID from "				    "Authenticator", ie.pmkid, PMKID_LEN);		}	}#endif /* CONFIG_NO_WPA2 */	if (wpa_supplicant_get_pmk(sm, src_addr, ie.pmkid))		return;	if (sm->renew_snonce) {		if (os_get_random(sm->snonce, WPA_NONCE_LEN)) {			wpa_msg(sm->ctx->ctx, MSG_WARNING,				"WPA: Failed to get random data for SNonce");			return;		}		sm->renew_snonce = 0;		wpa_hexdump(MSG_DEBUG, "WPA: Renewed SNonce",			    sm->snonce, WPA_NONCE_LEN);	}	/* Calculate PTK which will be stored as a temporary PTK until it has	 * been verified when processing message 3/4. */	ptk = &sm->tptk;	wpa_derive_ptk(sm, src_addr, key, ptk);	/* Supplicant: swap tx/rx Mic keys */	os_memcpy(buf, ptk->u.auth.tx_mic_key, 8);	os_memcpy(ptk->u.auth.tx_mic_key, ptk->u.auth.rx_mic_key, 8);	os_memcpy(ptk->u.auth.rx_mic_key, buf, 8);	sm->tptk_set = 1;	if (wpa_supplicant_send_2_of_4(sm, sm->bssid, key, ver, sm->snonce,				       sm->assoc_wpa_ie, sm->assoc_wpa_ie_len,				       ptk))		return;	os_memcpy(sm->anonce, key->key_nonce, WPA_NONCE_LEN);}static void wpa_sm_start_preauth(void *eloop_ctx, void *timeout_ctx){	struct wpa_sm *sm = eloop_ctx;	rsn_preauth_candidate_process(sm);}static void wpa_supplicant_key_neg_complete(struct wpa_sm *sm,					    const u8 *addr, int secure){	wpa_msg(sm->ctx->ctx, MSG_INFO, "WPA: Key negotiation completed with "		MACSTR " [PTK=%s GTK=%s]", MAC2STR(addr),		wpa_cipher_txt(sm->pairwise_cipher),		wpa_cipher_txt(sm->group_cipher));	wpa_sm_cancel_auth_timeout(sm);	wpa_sm_set_state(sm, WPA_COMPLETED);	if (secure) {		wpa_sm_mlme_setprotection(			sm, addr, MLME_SETPROTECTION_PROTECT_TYPE_RX_TX,			MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);		eapol_sm_notify_portValid(sm->eapol, TRUE);		if (wpa_key_mgmt_wpa_psk(sm->key_mgmt))			eapol_sm_notify_eap_success(sm->eapol, TRUE);		/*		 * Start preauthentication after a short wait to avoid a		 * possible race condition between the data receive and key

⌨️ 快捷键说明

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