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

📄 wpa.c

📁 hostapd无线AP工具
💻 C
📖 第 1 页 / 共 5 页
字号:
					sm->key_replay_counter,					WPA_REPLAY_COUNTER_LEN);			hostapd_hexdump("received replay counter",					key->replay_counter,					WPA_REPLAY_COUNTER_LEN);		}		return;	}	switch (msg) {	case PAIRWISE_2:		if (sm->wpa_ptk_state != WPA_PTK_PTKSTART &&		    sm->wpa_ptk_state != WPA_PTK_PTKCALCNEGOTIATING) {			hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,				       HOSTAPD_LEVEL_INFO,				       "received EAPOL-Key msg 2/4 in invalid"				       " state (%d) - dropped",				       sm->wpa_ptk_state);			return;		}		if (sta->wpa_ie == NULL ||		    sta->wpa_ie_len != key_data_length ||		    memcmp(sta->wpa_ie, key + 1, key_data_length) != 0) {			hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,				       HOSTAPD_LEVEL_INFO,				       "WPA IE from (Re)AssocReq did not match"				       " with msg 2/4");			if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MINIMAL)) {				if (sta->wpa_ie) {					hostapd_hexdump("WPA IE in AssocReq",							sta->wpa_ie,							sta->wpa_ie_len);				}				hostapd_hexdump("WPA IE in msg 2/4",						(u8 *) (key + 1),						key_data_length);			}			/* MLME-DEAUTHENTICATE.request */			wpa_sta_disconnect(hapd, sta);			return;		}		break;	case PAIRWISE_4:		if (sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING ||		    !sm->PTK_valid) {			hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,				       HOSTAPD_LEVEL_INFO,				       "received EAPOL-Key msg 4/4 in invalid"				       " state (%d) - dropped",				       sm->wpa_ptk_state);			return;		}		break;	case GROUP_2:		if (sm->wpa_ptk_group_state != WPA_PTK_GROUP_REKEYNEGOTIATING		    || !sm->PTK_valid) {			hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,				       HOSTAPD_LEVEL_INFO,				       "received EAPOL-Key msg 2/2 in invalid"				       " state (%d) - dropped",				       sm->wpa_ptk_group_state);			return;		}		break;	case REQUEST:		break;	}	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,		       HOSTAPD_LEVEL_DEBUG, "received EAPOL-Key frame (%s)",		       msgtxt);	if (key_info & WPA_KEY_INFO_ACK) {		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,			       HOSTAPD_LEVEL_INFO,			       "received invalid EAPOL-Key: Key Ack set");		return;	}	if (!(key_info & WPA_KEY_INFO_MIC)) {		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,			       HOSTAPD_LEVEL_INFO,			       "received invalid EAPOL-Key: Key MIC not set");		return;	}	sm->MICVerified = FALSE;	if (sm->PTK_valid) {		if (wpa_verify_key_mic(&sm->PTK, data, data_len)) {			hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,				       HOSTAPD_LEVEL_INFO,				       "received EAPOL-Key with invalid MIC");			return;		}		sm->MICVerified = TRUE;		eloop_cancel_timeout(wpa_send_eapol_timeout, sta->wpa_sm->hapd,				     sta);	}	if (key_info & WPA_KEY_INFO_REQUEST) {		if (sm->MICVerified) {			sta->req_replay_counter_used = 1;			memcpy(sta->req_replay_counter, key->replay_counter,			       WPA_REPLAY_COUNTER_LEN);		} else {			hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,				       HOSTAPD_LEVEL_INFO,				       "received EAPOL-Key request with "				       "invalid MIC");			return;		}		if (key_info & WPA_KEY_INFO_ERROR) {			/* Supplicant reported a Michael MIC error */			hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,				       HOSTAPD_LEVEL_INFO,				       "received EAPOL-Key Error Request "				       "(STA detected Michael MIC failure)");			ieee80211_michael_mic_failure(hapd, sta->addr, 0);			sta->dot11RSNAStatsTKIPRemoteMICFailures++;			hapd->wpa_auth->dot11RSNAStatsTKIPRemoteMICFailures++;			/* Error report is not a request for a new key			 * handshake, but since Authenticator may do it, let's			 * change the keys now anyway. */			wpa_request_new_ptk(hapd, sta);		} else if (key_info & WPA_KEY_INFO_KEY_TYPE) {			hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,				       HOSTAPD_LEVEL_INFO,				       "received EAPOL-Key Request for new "				       "4-Way Handshake");			wpa_request_new_ptk(hapd, sta);		} else {			/* TODO: this could also be a request for STAKey			 * if Key Data fields contains peer MAC address KDE.			 * STAKey request should have 0xdd <len> 00-0F-AC:2 in			 * the beginning of Key Data */			hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,				       HOSTAPD_LEVEL_INFO,				       "received EAPOL-Key Request for GTK "				       "rekeying");			wpa_request_new_ptk(hapd, sta);			eloop_cancel_timeout(wpa_rekey_gtk, hapd, NULL);			wpa_rekey_gtk(hapd, NULL);		}	} else {		/* Do not allow the same key replay counter to be reused. */		sm->key_replay_counter_valid = FALSE;	}	free(sm->last_rx_eapol_key);	sm->last_rx_eapol_key = malloc(data_len);	if (sm->last_rx_eapol_key == NULL)		return;	memcpy(sm->last_rx_eapol_key, data, data_len);	sm->last_rx_eapol_key_len = data_len;	sm->EAPOLKeyReceived = TRUE;	sm->EAPOLKeyPairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE);	sm->EAPOLKeyRequest = !!(key_info & WPA_KEY_INFO_REQUEST);	memcpy(sm->SNonce, key->key_nonce, WPA_NONCE_LEN);	wpa_sm_step(sm);}static void wpa_pmk_to_ptk(struct hostapd_data *hapd, const u8 *pmk,			   const u8 *addr1, const u8 *addr2,			   const u8 *nonce1, const u8 *nonce2,			   u8 *ptk, size_t ptk_len){	u8 data[2 * ETH_ALEN + 2 * WPA_NONCE_LEN];	/* PTK = PRF-X(PMK, "Pairwise key expansion",	 *             Min(AA, SA) || Max(AA, SA) ||	 *             Min(ANonce, SNonce) || Max(ANonce, SNonce)) */	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, WPA_NONCE_LEN) < 0) {		memcpy(data + 2 * ETH_ALEN, nonce1, WPA_NONCE_LEN);		memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce2,		       WPA_NONCE_LEN);	} else {		memcpy(data + 2 * ETH_ALEN, nonce2, WPA_NONCE_LEN);		memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce1,		       WPA_NONCE_LEN);	}	sha1_prf(pmk, WPA_PMK_LEN, "Pairwise key expansion",		 data, sizeof(data), ptk, ptk_len);	if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MINIMAL)) {		hostapd_hexdump("PMK", pmk, WPA_PMK_LEN);		hostapd_hexdump("PTK", ptk, ptk_len);	}}static void wpa_gmk_to_gtk(struct hostapd_data *hapd, u8 *gmk,			   u8 *addr, u8 *gnonce, u8 *gtk, size_t gtk_len){	u8 data[ETH_ALEN + WPA_NONCE_LEN];	/* GTK = PRF-X(GMK, "Group key expansion", AA || GNonce) */	memcpy(data, addr, ETH_ALEN);	memcpy(data + ETH_ALEN, gnonce, WPA_NONCE_LEN);	sha1_prf(gmk, WPA_GMK_LEN, "Group key expansion",		 data, sizeof(data), gtk, gtk_len);	if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MINIMAL)) {		hostapd_hexdump("GMK", gmk, WPA_GMK_LEN);		hostapd_hexdump("GTK", gtk, gtk_len);	}}static void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx){	struct hostapd_data *hapd = eloop_ctx;	struct sta_info *sta = timeout_ctx;	if (!sta->wpa_sm || !(sta->flags & WLAN_STA_ASSOC))		return;	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,		       HOSTAPD_LEVEL_DEBUG, "EAPOL-Key timeout");	sta->wpa_sm->TimeoutEvt = TRUE;	wpa_sm_step(sta->wpa_sm);}static int wpa_calc_eapol_key_mic(int ver, u8 *key, u8 *data, size_t len,				  u8 *mic){	u8 hash[SHA1_MAC_LEN];	switch (ver) {	case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4:		hmac_md5(key, 16, data, len, mic);		break;	case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES:		hmac_sha1(key, 16, data, len, hash);		memcpy(mic, hash, MD5_MAC_LEN);		break;	default:		return -1;	}	return 0;}static void wpa_send_eapol(struct hostapd_data *hapd, struct sta_info *sta,			   int secure, int mic, int ack, int install,			   int pairwise, u8 *key_rsc, u8 *nonce,			   u8 *ie, size_t ie_len, u8 *gtk, size_t gtk_len,			   int keyidx){	struct wpa_state_machine *sm = sta->wpa_sm;	struct ieee802_1x_hdr *hdr;	struct wpa_eapol_key *key;	size_t len;	int key_info, alg;	int timeout_ms;	int key_data_len, pad_len = 0;	u8 *buf, *pos;	if (sm == NULL)		return;	len = sizeof(struct ieee802_1x_hdr) + sizeof(struct wpa_eapol_key);	if (sta->wpa == WPA_VERSION_WPA2) {		key_data_len = ie_len + gtk_len;		if (gtk_len)			key_data_len += 2 + RSN_SELECTOR_LEN + 2;	} else {		if (pairwise) {			/* WPA does not include GTK in 4-Way Handshake */			gtk = NULL;			gtk_len = 0;			/* key_rsc is for group key, so mask it out in case of			 * WPA Pairwise key negotiation. */			key_rsc = NULL;		}		key_data_len = ie_len + gtk_len;	}	if (sta->pairwise == WPA_CIPHER_CCMP) {		key_info = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;		if (gtk) {			pad_len = key_data_len % 8;			if (pad_len)				pad_len = 8 - pad_len;			key_data_len += pad_len + 8;		}	} else {		key_info = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;	}	len += key_data_len;	hdr = malloc(len);	if (hdr == NULL)		return;	memset(hdr, 0, len);	hdr->version = EAPOL_VERSION;	hdr->type = IEEE802_1X_TYPE_EAPOL_KEY;	hdr->length = htons(len  - sizeof(*hdr));	key = (struct wpa_eapol_key *) (hdr + 1);	key->type = sta->wpa == WPA_VERSION_WPA2 ?		EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;	if (secure)		key_info |= WPA_KEY_INFO_SECURE;	if (mic)		key_info |= WPA_KEY_INFO_MIC;	if (ack)		key_info |= WPA_KEY_INFO_ACK;	if (install)		key_info |= WPA_KEY_INFO_INSTALL;	if (pairwise)		key_info |= WPA_KEY_INFO_KEY_TYPE;	if (gtk && sta->wpa == WPA_VERSION_WPA2)		key_info |= WPA_KEY_INFO_ENCR_KEY_DATA;	if (sta->wpa != WPA_VERSION_WPA2) {		if (pairwise)			keyidx = 0;		key_info |= keyidx << WPA_KEY_INFO_KEY_INDEX_SHIFT;	}	key->key_info = htons(key_info);	alg = pairwise ? sta->pairwise : hapd->conf->wpa_group;	switch (alg) {	case WPA_CIPHER_CCMP:		key->key_length = htons(16);		break;	case WPA_CIPHER_TKIP:		key->key_length = htons(32);		break;	case WPA_CIPHER_WEP40:		key->key_length = htons(5);		break;	case WPA_CIPHER_WEP104:		key->key_length = htons(13);		break;	}	inc_byte_array(sm->key_replay_counter, WPA_REPLAY_COUNTER_LEN);	memcpy(key->replay_counter, sm->key_replay_counter,	       WPA_REPLAY_COUNTER_LEN);	sm->key_replay_counter_valid = TRUE;	if (nonce)		memcpy(key->key_nonce, nonce, WPA_NONCE_LEN);	if (key_rsc)		memcpy(key->key_rsc, key_rsc, WPA_KEY_RSC_LEN);	if (ie && !gtk) {		memcpy(key + 1, ie, ie_len);		key->key_data_length = htons(ie_len);	} else if (gtk) {		buf = malloc(key_data_len);		if (buf == NULL) {			free(hdr);			return;		}		memset(buf, 0, key_data_len);		pos = buf;		if (ie) {			memcpy(pos, ie, ie_len);			pos += ie_len;		}		if (sta->wpa == WPA_VERSION_WPA2) {			*pos++ = WLAN_EID_GENERIC;			*pos++ = RSN_SELECTOR_LEN + 2 + gtk_len;			memcpy(pos, RSN_KEY_DATA_GROUPKEY, RSN_SELECTOR_LEN);			pos += RSN_SELECTOR_LEN;			*pos++ = keyidx & 0x03;			*pos++ = 0;		}		memcpy(pos, gtk, gtk_len);		pos += gtk_len;		if (pad_len)			*pos++ = 0xdd;		if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MINIMAL)) {			hostapd_hexdump("Plaintext EAPOL-Key Key Data",					buf, key_data_len);		}		if (key_info & WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {			aes_wrap(sm->PTK.encr_key, (key_data_len - 8) / 8, buf,				 (u8 *) (key + 1));			key->key_data_length = htons(key_data_len);		} else {			u8 ek[32];			memcpy(key->key_iv,			       hapd->wpa_auth->Counter + WPA_NONCE_LEN - 16,			       16);			inc_byte_array(hapd->wpa_auth->Counter, WPA_NONCE_LEN);			memcpy(ek, key->key_iv, 16);			memcpy(ek + 16, sm->PTK.encr_key, 16);			memcpy(key + 1, buf, key_data_len);			rc4_skip(ek, 32, 256, (u8 *) (key + 1), key_data_len);			key->key_data_length = htons(key_data_len);		}		free(buf);	}	if (mic) {		if (!sm->PTK_valid) {			hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,				       HOSTAPD_LEVEL_DEBUG, "PTK not valid "				       "when sending EAPOL-Key frame");			free(hdr);			return;		}		wpa_calc_eapol_key_mic(key_info & WPA_KEY_INFO_TYPE_MASK,				       sm->PTK.mic_key, (u8 *) hdr, len,				       key->key_mic);	}	if (sta->eapol_sm)		sta->eapol_sm->dot1xAuthEapolFramesTx++;	hostapd_send_eapol(hapd, sta->addr, (u8 *) hdr, len, sm->pairwise_set);	free(hdr);	timeout_ms = pairwise ? dot11RSNAConfigPairwiseUpdateTimeOut :		dot11RSNAConfigGroupUpdateTimeOut;	eloop_register_timeout(timeout_ms / 1000, (timeout_ms % 1000) * 1000,			       wpa_send_eapol_timeout, hapd, sta);}static int wpa_verify_key_mic(struct wpa_ptk *PTK, u8 *data, size_t data_len){	struct ieee802_1x_hdr *hdr;	struct wpa_eapol_key *key;	u16 key_info;	int type, ret = 0;	u8 mic[16];	if (data_len < sizeof(*hdr) + sizeof(*key))		return -1;	hdr = (struct ieee802_1x_hdr *) data;	key = (struct wpa_eapol_key *) (hdr + 1);	key_info = ntohs(key->key_info);	type = key_info & WPA_KEY_INFO_TYPE_MASK;	memcpy(mic, key->key_mic, 16);	memset(key->key_mic, 0, 16);	if (wpa_calc_eapol_key_mic(key_info & WPA_KEY_INFO_TYPE_MASK,				   PTK->mic_key, data, data_len, key->key_mic)	    || memcmp(mic, key->key_mic, 16) != 0)		ret = -1;	memcpy(key->key_mic, mic, 16);	return ret;}void wpa_sm_event(struct hostapd_data *hapd, struct sta_info *sta,		  wpa_event event){	struct wpa_state_machine *sm = sta->wpa_sm;	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,		       HOSTAPD_LEVEL_DEBUG,		       "event %d notification", event);	if (sm == NULL)		return;	switch (event) {	case WPA_AUTH:	case WPA_ASSOC:		break;	case WPA_DEAUTH:	case WPA_DISASSOC:		sm->DeauthenticationRequest = TRUE;		break;	case WPA_REAUTH:	case WPA_REAUTH_EAPOL:		sm->ReAuthenticationRequest = TRUE;

⌨️ 快捷键说明

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