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

📄 wpa.c

📁 hostapd源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	}	neg->num_retries++;	if (neg->num_retries > dot11RSNAConfigPairwiseUpdateCount) {		wpa_printf(MSG_DEBUG, "RSN: STAKey handshake with " MACSTR			   " timed out", MAC2STR(dst));		wpa_stakey_remove(wpa_auth, neg);		return;	}	wpa_printf(MSG_DEBUG, "RSN: Sending STAKey 1/2 to " MACSTR " (try=%d)",		   MAC2STR(dst), neg->num_retries);	memset(&kde, 0, sizeof(kde));	kde.id = GENERIC_INFO_ELEM;	kde.len = sizeof(kde) - 2 - 32 + neg->key_len;	memcpy(kde.oui, RSN_KEY_DATA_STAKEY, RSN_SELECTOR_LEN);	memcpy(kde.mac_addr, peer, ETH_ALEN);	memcpy(kde.stakey, neg->key, neg->key_len);	if (neg->alg == WPA_CIPHER_CCMP)		version = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;	else		version = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;	__wpa_send_eapol(wpa_auth, search.sm, 1, 1, 1, 0, 0, NULL,			 NULL /* nonce */,			 (u8 *) &kde, sizeof(kde) - 32 + neg->key_len,			 NULL, 0, 0, 1, version);	eloop_register_timeout(dot11RSNAConfigPairwiseUpdateTimeOut / 1000,			       (dot11RSNAConfigPairwiseUpdateTimeOut % 1000) *			       1000, wpa_stakey_step, wpa_auth, neg);}#endif /* CONFIG_STAKEY */static int wpa_stakey_remove(struct wpa_authenticator *wpa_auth,			     struct wpa_stakey_negotiation *neg){#ifdef CONFIG_STAKEY	struct wpa_stakey_negotiation *pos, *prev;	if (wpa_auth == NULL)		return -1;	pos = wpa_auth->stakey_negotiations;	prev = NULL;	while (pos) {		if (pos == neg) {			if (prev)				prev->next = pos->next;			else				wpa_auth->stakey_negotiations = pos->next;			eloop_cancel_timeout(wpa_stakey_step, wpa_auth, pos);			free(pos);			return 0;		}		prev = pos;		pos = pos->next;	}#endif /* CONFIG_STAKEY */	return -1;}#ifdef CONFIG_STAKEYstatic int wpa_stakey_initiate(struct wpa_authenticator *wpa_auth,			       const u8 *initiator, const u8 *peer, int alg){	struct wpa_stakey_negotiation *neg;	if (wpa_auth == NULL)		return -1;	neg = wpa_stakey_get(wpa_auth, initiator, peer);	if (neg) {		wpa_printf(MSG_DEBUG, "RSN: Pending STAKey handshake in "			   "progress - ignoring new request");		return -1;	}	neg = wpa_zalloc(sizeof(*neg));	if (neg == NULL)		return -1;	memcpy(neg->initiator, initiator, ETH_ALEN);	memcpy(neg->peer, peer, ETH_ALEN);	neg->state = PEER;	neg->alg = alg;	if (alg == WPA_CIPHER_TKIP)		neg->key_len = 32;	else		neg->key_len = 16;	if (hostapd_get_rand(neg->key, neg->key_len)) {		wpa_printf(MSG_DEBUG, "RSN: Failed to get random data for "			   "STAKey");		free(neg);		return -1;	}	neg->next = wpa_auth->stakey_negotiations;	wpa_auth->stakey_negotiations = neg;	wpa_stakey_step(wpa_auth, neg);	return 0;}#endif /* CONFIG_STAKEY */static void wpa_stakey_receive(struct wpa_authenticator *wpa_auth,			       const u8 *src_addr, const u8 *peer){#ifdef CONFIG_STAKEY	struct wpa_stakey_negotiation *neg;	neg = wpa_stakey_get(wpa_auth, src_addr, peer);	if (neg == NULL) {		wpa_printf(MSG_DEBUG, "RSN: No matching STAKey negotiation "			   "found - ignored received STAKey frame");		return;	}	if (neg->state == PEER &&	    memcmp(src_addr, neg->peer, ETH_ALEN) == 0) {		neg->state = INITIATOR;		neg->num_retries = 0;		wpa_printf(MSG_DEBUG, "RSN: STAKey completed with peer "			   MACSTR, MAC2STR(neg->peer));		eloop_cancel_timeout(wpa_stakey_step, wpa_auth, neg);		wpa_stakey_step(wpa_auth, neg);	} else if (neg->state == INITIATOR &&		   memcmp(src_addr, neg->initiator, ETH_ALEN) == 0) {		wpa_printf(MSG_DEBUG, "RSN: STAKey negotiation completed "			   MACSTR " <-> " MACSTR,			   MAC2STR(neg->initiator), MAC2STR(neg->peer));		wpa_stakey_remove(wpa_auth, neg);	} else {		wpa_printf(MSG_DEBUG, "RSN: Unexpected STAKey message - "			   "src " MACSTR " peer " MACSTR " - dropped",			   MAC2STR(src_addr), MAC2STR(peer));	}#endif /* CONFIG_STAKEY */}void wpa_receive(struct wpa_authenticator *wpa_auth,		 struct wpa_state_machine *sm,		 u8 *data, size_t data_len){	struct ieee802_1x_hdr *hdr;	struct wpa_eapol_key *key;	u16 key_info, key_data_length;	enum { PAIRWISE_2, PAIRWISE_4, GROUP_2, STAKEY_2, REQUEST } msg;	char *msgtxt;	struct wpa_eapol_ie_parse kde;	const u8 *mac_addr = NULL;	if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL)		return;	if (data_len < sizeof(*hdr) + sizeof(*key))		return;	hdr = (struct ieee802_1x_hdr *) data;	key = (struct wpa_eapol_key *) (hdr + 1);	key_info = ntohs(key->key_info);	key_data_length = ntohs(key->key_data_length);	if (key_data_length > data_len - sizeof(*hdr) - sizeof(*key)) {		wpa_printf(MSG_INFO, "WPA: Invalid EAPOL-Key frame - "			   "key_data overflow (%d > %lu)",			   key_data_length,			   (unsigned long) (data_len - sizeof(*hdr) -					    sizeof(*key)));		return;	}	/* FIX: verify that the EAPOL-Key frame was encrypted if pairwise keys	 * are set */	if (key_info & WPA_KEY_INFO_REQUEST) {		msg = REQUEST;		msgtxt = "Request";	} else if (!(key_info & WPA_KEY_INFO_KEY_TYPE)) {		/* FIX: should decrypt key_data if encrypted */		if (key_data_length > 0 &&		    wpa_parse_kde_ies((const u8 *) (key + 1),				      key_data_length, &kde) == 0 &&		    kde.mac_addr) {			msg = STAKEY_2;			msgtxt = "2/2 STAKey";			mac_addr = kde.mac_addr;		} else {			msg = GROUP_2;			msgtxt = "2/2 Group";		}	} else if (key_data_length == 0) {		msg = PAIRWISE_4;		msgtxt = "4/4 Pairwise";	} else {		msg = PAIRWISE_2;		msgtxt = "2/4 Pairwise";	}	if (key_info & WPA_KEY_INFO_REQUEST) {		if (sm->req_replay_counter_used &&		    memcmp(key->replay_counter, sm->req_replay_counter,			   WPA_REPLAY_COUNTER_LEN) <= 0) {			wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING,					"received EAPOL-Key request with "					"replayed counter");			return;		}	}	if (!(key_info & WPA_KEY_INFO_REQUEST) &&	    (!sm->key_replay_counter_valid ||	     memcmp(key->replay_counter, sm->key_replay_counter,		    WPA_REPLAY_COUNTER_LEN) != 0)) {		wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,				 "received EAPOL-Key %s with unexpected "				 "replay counter", msgtxt);		wpa_hexdump(MSG_DEBUG, "expected replay counter",			    sm->key_replay_counter, WPA_REPLAY_COUNTER_LEN);		wpa_hexdump(MSG_DEBUG, "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) {			wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,					 "received EAPOL-Key msg 2/4 in "					 "invalid state (%d) - dropped",					 sm->wpa_ptk_state);			return;		}		if (sm->wpa_ie == NULL ||		    sm->wpa_ie_len != key_data_length ||		    memcmp(sm->wpa_ie, key + 1, key_data_length) != 0) {			wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,					"WPA IE from (Re)AssocReq did not "					"match with msg 2/4");			if (sm->wpa_ie) {				wpa_hexdump(MSG_DEBUG, "WPA IE in AssocReq",					    sm->wpa_ie, sm->wpa_ie_len);			}			wpa_hexdump(MSG_DEBUG, "WPA IE in msg 2/4",				    (u8 *) (key + 1), key_data_length);			/* MLME-DEAUTHENTICATE.request */			wpa_sta_disconnect(wpa_auth, sm->addr);			return;		}		break;	case PAIRWISE_4:		if (sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING ||		    !sm->PTK_valid) {			wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_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) {			wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,					 "received EAPOL-Key msg 2/2 in "					 "invalid state (%d) - dropped",					 sm->wpa_ptk_group_state);			return;		}		break;	case STAKEY_2:		if (!sm->PTK_valid) {			wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,					"received EAPOL-Key msg STAKey 2/2 in "					"invalid state - dropped");			return;		}		break;	case REQUEST:		break;	}	wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,			 "received EAPOL-Key frame (%s)", msgtxt);	if (key_info & WPA_KEY_INFO_ACK) {		wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,				"received invalid EAPOL-Key: Key Ack set");		return;	}	if (!(key_info & WPA_KEY_INFO_MIC)) {		wpa_auth_logger(wpa_auth, sm->addr, LOGGER_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)) {			wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,					"received EAPOL-Key with invalid MIC");			return;		}		sm->MICVerified = TRUE;		eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm);	}	if (key_info & WPA_KEY_INFO_REQUEST) {		if (sm->MICVerified) {			sm->req_replay_counter_used = 1;			memcpy(sm->req_replay_counter, key->replay_counter,			       WPA_REPLAY_COUNTER_LEN);		} else {			wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,					"received EAPOL-Key request with "					"invalid MIC");			return;		}		/*		 * TODO: should decrypt key data field if encryption was used;		 * even though MAC address KDE is not normally encrypted,		 * supplicant is allowed to encrypt it.		 */		if (key_info & WPA_KEY_INFO_ERROR) {			/* Supplicant reported a Michael MIC error */			wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,					"received EAPOL-Key Error Request "					"(STA detected Michael MIC failure)");			wpa_auth_mic_failure_report(wpa_auth, sm->addr);			sm->dot11RSNAStatsTKIPRemoteMICFailures++;			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(sm);		} else if (key_info & WPA_KEY_INFO_KEY_TYPE) {			wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,					"received EAPOL-Key Request for new "					"4-Way Handshake");			wpa_request_new_ptk(sm);		} else if (key_data_length > 0 &&			   wpa_parse_kde_ies((const u8 *) (key + 1),					     key_data_length, &kde) == 0 &&			   kde.mac_addr) {#ifdef CONFIG_STAKEY			/* STAKey Request */			if (!wpa_auth->conf.stakey) {				wpa_printf(MSG_DEBUG, "RSN: STAKey Request, "					   "but STAKey use disabled - ignoring"					   " request");			} else if (kde.mac_addr_len != ETH_ALEN) {				wpa_printf(MSG_DEBUG, "RSN: Invalid MAC "					   "address KDE length %d",					   kde.mac_addr_len);			} else {				int alg;				wpa_printf(MSG_DEBUG, "RSN: STAKey Request for"					   " peer " MACSTR,					   MAC2STR(kde.mac_addr));				switch (key_info & WPA_KEY_INFO_TYPE_MASK) {				case 1:					alg = WPA_CIPHER_TKIP;					break;				case 2:					alg = WPA_CIPHER_CCMP;					break;				default:					wpa_printf(MSG_DEBUG, "Unexpected "						   "STAKey key version (%d)",						   key_info &						   WPA_KEY_INFO_TYPE_MASK);					alg = WPA_CIPHER_NONE;					break;				}				if (alg != WPA_CIPHER_NONE) {					wpa_stakey_initiate(wpa_auth, sm->addr,							    kde.mac_addr, alg);				}			}#endif /* CONFIG_STAKEY */		} else {			wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,					"received EAPOL-Key Request for GTK "					"rekeying");			/* FIX: why was this triggering PTK rekeying for the			 * STA that requested Group Key rekeying?? */			/* wpa_request_new_ptk(sta->wpa_sm); */			eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL);			wpa_rekey_gtk(wpa_auth, NULL);		}	} else {		/* Do not allow the same key replay counter to be reused. */		sm->key_replay_counter_valid = FALSE;	}	if (msg == STAKEY_2) {		wpa_stakey_receive(wpa_auth, sm->addr, mac_addr);		return;	}	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(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);	wpa_hexdump_key(MSG_DEBUG, "PMK", pmk, WPA_PMK_LEN);	wpa_hexdump_key(MSG_DEBUG, "PTK", ptk, ptk_len);}static void wpa_gmk_to_gtk(const u8 *gmk, const u8 *addr, const 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);	wpa_hexdump_key(MSG_DEBUG, "GMK", gmk, WPA_GMK_LEN);	wpa_hexdump_key(MSG_DEBUG, "GTK", gtk, gtk_len);}static void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx){	struct wpa_authenticator *wpa_auth = eloop_ctx;	struct wpa_state_machine *sm = timeout_ctx;	wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "EAPOL-Key timeout");	sm->TimeoutEvt = TRUE;	wpa_sm_step(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) {

⌨️ 快捷键说明

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