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

📄 wpa.c

📁 最新的Host AP 新添加了许多pcmcia 的驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (sm->ft_completed) {		wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,				"FT authentication already completed - do not "				"start 4-way handshake");		return;	}#endif /* CONFIG_IEEE80211R */	if (sm->started) {		os_memset(&sm->key_replay, 0, sizeof(sm->key_replay));		sm->ReAuthenticationRequest = TRUE;		wpa_sm_step(sm);		return;	}	wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,			"start authentication");	sm->started = 1;	sm->Init = TRUE;	wpa_sm_step(sm);	sm->Init = FALSE;	sm->AuthenticationRequest = TRUE;	wpa_sm_step(sm);}void wpa_auth_sta_no_wpa(struct wpa_state_machine *sm){	/* WPA/RSN was not used - clear WPA state. This is needed if the STA	 * reassociates back to the same AP while the previous entry for the	 * STA has not yet been removed. */	if (sm == NULL)		return;	sm->wpa_key_mgmt = 0;}static void wpa_free_sta_sm(struct wpa_state_machine *sm){	os_free(sm->last_rx_eapol_key);	os_free(sm->wpa_ie);	os_free(sm);}void wpa_auth_sta_deinit(struct wpa_state_machine *sm){	if (sm == NULL)		return;	if (sm->wpa_auth->conf.wpa_strict_rekey && sm->has_GTK) {		wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,				"strict rekeying - force GTK rekey since STA "				"is leaving");		eloop_cancel_timeout(wpa_rekey_gtk, sm->wpa_auth, NULL);		eloop_register_timeout(0, 500000, wpa_rekey_gtk, sm->wpa_auth,				       NULL);	}	eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm);	eloop_cancel_timeout(wpa_sm_call_step, sm, NULL);	eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm);	if (sm->in_step_loop) {		/* Must not free state machine while wpa_sm_step() is running.		 * Freeing will be completed in the end of wpa_sm_step(). */		wpa_printf(MSG_DEBUG, "WPA: Registering pending STA state "			   "machine deinit for " MACSTR, MAC2STR(sm->addr));		sm->pending_deinit = 1;	} else		wpa_free_sta_sm(sm);}static void wpa_request_new_ptk(struct wpa_state_machine *sm){	if (sm == NULL)		return;	sm->PTKRequest = TRUE;	sm->PTK_valid = 0;}static int wpa_replay_counter_valid(struct wpa_state_machine *sm,				    const u8 *replay_counter){	int i;	for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) {		if (!sm->key_replay[i].valid)			break;		if (os_memcmp(replay_counter, sm->key_replay[i].counter,			      WPA_REPLAY_COUNTER_LEN) == 0)			return 1;	}	return 0;}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, REQUEST,	       SMK_M1, SMK_M3, SMK_ERROR } msg;	char *msgtxt;	struct wpa_eapol_ie_parse kde;	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 = WPA_GET_BE16(key->key_info);	key_data_length = WPA_GET_BE16(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_SMK_MESSAGE | WPA_KEY_INFO_REQUEST)) ==	    (WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_REQUEST)) {		if (key_info & WPA_KEY_INFO_ERROR) {			msg = SMK_ERROR;			msgtxt = "SMK Error";		} else {			msg = SMK_M1;			msgtxt = "SMK M1";		}	} else if (key_info & WPA_KEY_INFO_SMK_MESSAGE) {		msg = SMK_M3;		msgtxt = "SMK M3";	} else if (key_info & WPA_KEY_INFO_REQUEST) {		msg = REQUEST;		msgtxt = "Request";	} else if (!(key_info & WPA_KEY_INFO_KEY_TYPE)) {		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";	}	/* TODO: key_info type validation for PeerKey */	if (msg == REQUEST || msg == PAIRWISE_2 || msg == PAIRWISE_4 ||	    msg == GROUP_2) {		u16 ver = key_info & WPA_KEY_INFO_TYPE_MASK;		if (sm->pairwise == WPA_CIPHER_CCMP) {			if (wpa_use_aes_cmac(sm) &&			    ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) {				wpa_auth_logger(wpa_auth, sm->addr,						LOGGER_WARNING,						"advertised support for "						"AES-128-CMAC, but did not "						"use it");				return;			}			if (!wpa_use_aes_cmac(sm) &&			    ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {				wpa_auth_logger(wpa_auth, sm->addr,						LOGGER_WARNING,						"did not use HMAC-SHA1-AES "						"with CCMP");				return;			}		}	}	if (key_info & WPA_KEY_INFO_REQUEST) {		if (sm->req_replay_counter_used &&		    os_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) &&	    !wpa_replay_counter_valid(sm, key->replay_counter)) {		int i;		wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,				 "received EAPOL-Key %s with unexpected "				 "replay counter", msgtxt);		for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) {			if (!sm->key_replay[i].valid)				break;			wpa_hexdump(MSG_DEBUG, "pending replay counter",				    sm->key_replay[i].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 ||		    os_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;#ifdef CONFIG_PEERKEY	case SMK_M1:	case SMK_M3:	case SMK_ERROR:		if (!wpa_auth->conf.peerkey) {			wpa_printf(MSG_DEBUG, "RSN: SMK M1/M3/Error, but "				   "PeerKey use disabled - ignoring message");			return;		}		if (!sm->PTK_valid) {			wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,					"received EAPOL-Key msg SMK in "					"invalid state - dropped");			return;		}		break;#else /* CONFIG_PEERKEY */	case SMK_M1:	case SMK_M3:	case SMK_ERROR:		return; /* STSL disabled - ignore SMK messages */#endif /* CONFIG_PEERKEY */	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;			os_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 (msg == SMK_ERROR) {#ifdef CONFIG_PEERKEY			wpa_smk_error(wpa_auth, sm, key);#endif /* CONFIG_PEERKEY */			return;		} else 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);#ifdef CONFIG_PEERKEY		} else if (msg == SMK_M1) {			wpa_smk_m1(wpa_auth, sm, key);#endif /* CONFIG_PEERKEY */		} else if (key_data_length > 0 &&			   wpa_parse_kde_ies((const u8 *) (key + 1),					     key_data_length, &kde) == 0 &&			   kde.mac_addr) {		} 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. This		 * does also invalidate all other pending replay counters if		 * retransmissions were used, i.e., we will only process one of		 * the pending replies and ignore rest if more than one is		 * received. */		sm->key_replay[0].valid = FALSE;	}#ifdef CONFIG_PEERKEY	if (msg == SMK_M3) {		wpa_smk_m3(wpa_auth, sm, key);		return;	}#endif /* CONFIG_PEERKEY */	os_free(sm->last_rx_eapol_key);	sm->last_rx_eapol_key = os_malloc(data_len);	if (sm->last_rx_eapol_key == NULL)		return;	os_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);	os_memcpy(sm->SNonce, key->key_nonce, WPA_NONCE_LEN);	wpa_sm_step(sm);}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) */	os_memcpy(data, addr, ETH_ALEN);	os_memcpy(data + ETH_ALEN, gnonce, WPA_NONCE_LEN);#ifdef CONFIG_IEEE80211W	sha256_prf(gmk, WPA_GMK_LEN, "Group key expansion",		   data, sizeof(data), gtk, gtk_len);#else /* CONFIG_IEEE80211W */	sha1_prf(gmk, WPA_GMK_LEN, "Group key expansion",		 data, sizeof(data), gtk, gtk_len);#endif /* CONFIG_IEEE80211W */	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);}void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,		      struct wpa_state_machine *sm, int key_info,		      const u8 *key_rsc, const u8 *nonce,		      const u8 *kde, size_t kde_len,		      int keyidx, int encr, int force_version){	struct ieee802_1x_hdr *hdr;	struct wpa_eapol_key *key;	size_t len;	int alg;	int key_data_len, pad_len = 0;	u8 *buf, *pos;	int version, pairwise;	int i;	len = sizeof(struct ieee802_1x_hdr) + sizeof(struct wpa_eapol_key);	if (force_version)		version = force_version;	else if (wpa_use_aes_cmac(sm))		version = WPA_KEY_INFO_TYPE_AES_128_CMAC;	else if (sm->pairwise == WPA_CIPHER_CCMP)		version = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;	else		version = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;	pairwise = key_info & WPA_KEY_INFO_KEY_TYPE;	wpa_printf(MSG_DEBUG, "WPA: Send EAPOL(version=%d secure=%d mic=%d "		   "ack=%d install=%d pairwise=%d kde_len=%lu keyidx=%d "		   "encr=%d)",		   version,		   (key_info & WPA_KEY_INFO_SECURE) ? 1 : 0,		   (key_info & WPA_KEY_INFO_MIC) ? 1 : 0,		   (key_info & WPA_KEY_INFO_ACK) ? 1 : 0,		   (key_info & WPA_KEY_INFO_INSTALL) ? 1 : 0,		   pairwise, (unsigned long) kde_len, keyidx, encr);	key_data_len = kde_len;	if ((version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||	     version == WPA_KEY_INFO_TYPE_AES_128_CMAC) && encr) {		pad_len = key_data_len % 8;		if (pad_len)			pad_len = 8 - pad_len;		key_data_len += pad_len + 8;	}	len += key_data_len;	hdr = os_zalloc(len);	if (hdr == NULL)		return;	hdr->version = wpa_auth->conf.eapol_version;	hdr->type = IEEE802_1X_TYPE_EAPOL_KEY;

⌨️ 快捷键说明

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