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

📄 wpa.c

📁 最新的Host AP 新添加了许多pcmcia 的驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
	hdr->length = host_to_be16(len  - sizeof(*hdr));	key = (struct wpa_eapol_key *) (hdr + 1);	key->type = sm->wpa == WPA_VERSION_WPA2 ?		EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;	key_info |= version;	if (encr && sm->wpa == WPA_VERSION_WPA2)		key_info |= WPA_KEY_INFO_ENCR_KEY_DATA;	if (sm->wpa != WPA_VERSION_WPA2)		key_info |= keyidx << WPA_KEY_INFO_KEY_INDEX_SHIFT;	WPA_PUT_BE16(key->key_info, key_info);	alg = pairwise ? sm->pairwise : wpa_auth->conf.wpa_group;	switch (alg) {	case WPA_CIPHER_CCMP:		WPA_PUT_BE16(key->key_length, 16);		break;	case WPA_CIPHER_TKIP:		WPA_PUT_BE16(key->key_length, 32);		break;	case WPA_CIPHER_WEP40:		WPA_PUT_BE16(key->key_length, 5);		break;	case WPA_CIPHER_WEP104:		WPA_PUT_BE16(key->key_length, 13);		break;	}	if (key_info & WPA_KEY_INFO_SMK_MESSAGE)		WPA_PUT_BE16(key->key_length, 0);	/* FIX: STSL: what to use as key_replay_counter? */	for (i = RSNA_MAX_EAPOL_RETRIES - 1; i > 0; i--) {		sm->key_replay[i].valid = sm->key_replay[i - 1].valid;		os_memcpy(sm->key_replay[i].counter,			  sm->key_replay[i - 1].counter,			  WPA_REPLAY_COUNTER_LEN);	}	inc_byte_array(sm->key_replay[0].counter, WPA_REPLAY_COUNTER_LEN);	os_memcpy(key->replay_counter, sm->key_replay[0].counter,		  WPA_REPLAY_COUNTER_LEN);	sm->key_replay[0].valid = TRUE;	if (nonce)		os_memcpy(key->key_nonce, nonce, WPA_NONCE_LEN);	if (key_rsc)		os_memcpy(key->key_rsc, key_rsc, WPA_KEY_RSC_LEN);	if (kde && !encr) {		os_memcpy(key + 1, kde, kde_len);		WPA_PUT_BE16(key->key_data_length, kde_len);	} else if (encr && kde) {		buf = os_zalloc(key_data_len);		if (buf == NULL) {			os_free(hdr);			return;		}		pos = buf;		os_memcpy(pos, kde, kde_len);		pos += kde_len;		if (pad_len)			*pos++ = 0xdd;		wpa_hexdump_key(MSG_DEBUG, "Plaintext EAPOL-Key Key Data",				buf, key_data_len);		if (version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||		    version == WPA_KEY_INFO_TYPE_AES_128_CMAC) {			if (aes_wrap(sm->PTK.kek, (key_data_len - 8) / 8, buf,				     (u8 *) (key + 1))) {				os_free(hdr);				os_free(buf);				return;			}			WPA_PUT_BE16(key->key_data_length, key_data_len);		} else {			u8 ek[32];			os_memcpy(key->key_iv,				  sm->group->Counter + WPA_NONCE_LEN - 16, 16);			inc_byte_array(sm->group->Counter, WPA_NONCE_LEN);			os_memcpy(ek, key->key_iv, 16);			os_memcpy(ek + 16, sm->PTK.kek, 16);			os_memcpy(key + 1, buf, key_data_len);			rc4_skip(ek, 32, 256, (u8 *) (key + 1), key_data_len);			WPA_PUT_BE16(key->key_data_length, key_data_len);		}		os_free(buf);	}	if (key_info & WPA_KEY_INFO_MIC) {		if (!sm->PTK_valid) {			wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,					"PTK not valid when sending EAPOL-Key "					"frame");			os_free(hdr);			return;		}		wpa_eapol_key_mic(sm->PTK.kck, version, (u8 *) hdr, len,				  key->key_mic);	}	wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_inc_EapolFramesTx,			   1);	wpa_auth_send_eapol(wpa_auth, sm->addr, (u8 *) hdr, len,			    sm->pairwise_set);	os_free(hdr);}static 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 timeout_ms;	int pairwise = key_info & WPA_KEY_INFO_KEY_TYPE;	int ctr;	if (sm == NULL)		return;	__wpa_send_eapol(wpa_auth, sm, key_info, key_rsc, nonce, kde, kde_len,			 keyidx, encr, 0);	ctr = pairwise ? sm->TimeoutCtr : sm->GTimeoutCtr;	if (ctr == 1)		timeout_ms = eapol_key_timeout_first;	else		timeout_ms = eapol_key_timeout_subseq;	eloop_register_timeout(timeout_ms / 1000, (timeout_ms % 1000) * 1000,			       wpa_send_eapol_timeout, wpa_auth, sm);}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 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 = WPA_GET_BE16(key->key_info);	os_memcpy(mic, key->key_mic, 16);	os_memset(key->key_mic, 0, 16);	if (wpa_eapol_key_mic(PTK->kck, key_info & WPA_KEY_INFO_TYPE_MASK,			      data, data_len, key->key_mic) ||	    os_memcmp(mic, key->key_mic, 16) != 0)		ret = -1;	os_memcpy(key->key_mic, mic, 16);	return ret;}void wpa_remove_ptk(struct wpa_state_machine *sm){	sm->PTK_valid = FALSE;	os_memset(&sm->PTK, 0, sizeof(sm->PTK));	wpa_auth_set_key(sm->wpa_auth, 0, "none", sm->addr, 0, (u8 *) "", 0);	sm->pairwise_set = FALSE;	eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm);}void wpa_auth_sm_event(struct wpa_state_machine *sm, wpa_event event){	int remove_ptk = 1;	if (sm == NULL)		return;	wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,			 "event %d notification", event);	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:		if (sm->GUpdateStationKeys) {			/*			 * Reauthentication cancels the pending group key			 * update for this STA.			 */			sm->group->GKeyDoneStations--;			sm->GUpdateStationKeys = FALSE;			sm->PtkGroupInit = TRUE;		}		sm->ReAuthenticationRequest = TRUE;		break;	case WPA_ASSOC_FT:#ifdef CONFIG_IEEE80211R		/* Using FT protocol, not WPA auth state machine */		sm->ft_completed = 1;		return;#else /* CONFIG_IEEE80211R */		break;#endif /* CONFIG_IEEE80211R */	}#ifdef CONFIG_IEEE80211R	sm->ft_completed = 0;#endif /* CONFIG_IEEE80211R */#ifdef CONFIG_IEEE80211W	if (sm->mgmt_frame_prot && event == WPA_AUTH)		remove_ptk = 0;#endif /* CONFIG_IEEE80211W */	if (remove_ptk) {		sm->PTK_valid = FALSE;		os_memset(&sm->PTK, 0, sizeof(sm->PTK));		if (event != WPA_REAUTH_EAPOL)			wpa_remove_ptk(sm);	}	wpa_sm_step(sm);}static const char * wpa_alg_txt(int alg){	switch (alg) {	case WPA_CIPHER_CCMP:		return "CCMP";	case WPA_CIPHER_TKIP:		return "TKIP";	case WPA_CIPHER_WEP104:	case WPA_CIPHER_WEP40:		return "WEP";	default:		return "";	}}SM_STATE(WPA_PTK, INITIALIZE){	SM_ENTRY_MA(WPA_PTK, INITIALIZE, wpa_ptk);	if (sm->Init) {		/* Init flag is not cleared here, so avoid busy		 * loop by claiming nothing changed. */		sm->changed = FALSE;	}	sm->keycount = 0;	if (sm->GUpdateStationKeys)		sm->group->GKeyDoneStations--;	sm->GUpdateStationKeys = FALSE;	if (sm->wpa == WPA_VERSION_WPA)		sm->PInitAKeys = FALSE;	if (1 /* Unicast cipher supported AND (ESS OR ((IBSS or WDS) and	       * Local AA > Remote AA)) */) {		sm->Pair = TRUE;	}	wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 0);	wpa_remove_ptk(sm);	wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid, 0);	sm->TimeoutCtr = 0;	if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) {		wpa_auth_set_eapol(sm->wpa_auth, sm->addr,				   WPA_EAPOL_authorized, 0);	}}SM_STATE(WPA_PTK, DISCONNECT){	SM_ENTRY_MA(WPA_PTK, DISCONNECT, wpa_ptk);	sm->Disconnect = FALSE;	wpa_sta_disconnect(sm->wpa_auth, sm->addr);}SM_STATE(WPA_PTK, DISCONNECTED){	SM_ENTRY_MA(WPA_PTK, DISCONNECTED, wpa_ptk);	sm->DeauthenticationRequest = FALSE;}SM_STATE(WPA_PTK, AUTHENTICATION){	SM_ENTRY_MA(WPA_PTK, AUTHENTICATION, wpa_ptk);	os_memset(&sm->PTK, 0, sizeof(sm->PTK));	sm->PTK_valid = FALSE;	wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portControl_Auto,			   1);	wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 1);	sm->AuthenticationRequest = FALSE;}SM_STATE(WPA_PTK, AUTHENTICATION2){	SM_ENTRY_MA(WPA_PTK, AUTHENTICATION2, wpa_ptk);	os_memcpy(sm->ANonce, sm->group->Counter, WPA_NONCE_LEN);	inc_byte_array(sm->group->Counter, WPA_NONCE_LEN);	sm->ReAuthenticationRequest = FALSE;	/* IEEE 802.11i does not clear TimeoutCtr here, but this is more	 * logical place than INITIALIZE since AUTHENTICATION2 can be	 * re-entered on ReAuthenticationRequest without going through	 * INITIALIZE. */	sm->TimeoutCtr = 0;}SM_STATE(WPA_PTK, INITPMK){	u8 msk[2 * PMK_LEN];	size_t len = 2 * PMK_LEN;	SM_ENTRY_MA(WPA_PTK, INITPMK, wpa_ptk);#ifdef CONFIG_IEEE80211R	sm->xxkey_len = 0;#endif /* CONFIG_IEEE80211R */	if (sm->pmksa) {		wpa_printf(MSG_DEBUG, "WPA: PMK from PMKSA cache");		os_memcpy(sm->PMK, sm->pmksa->pmk, PMK_LEN);	} else if (wpa_auth_get_msk(sm->wpa_auth, sm->addr, msk, &len) == 0) {		wpa_printf(MSG_DEBUG, "WPA: PMK from EAPOL state machine "			   "(len=%lu)", (unsigned long) len);		os_memcpy(sm->PMK, msk, PMK_LEN);#ifdef CONFIG_IEEE80211R		if (len >= 2 * PMK_LEN) {			os_memcpy(sm->xxkey, msk + PMK_LEN, PMK_LEN);			sm->xxkey_len = PMK_LEN;		}#endif /* CONFIG_IEEE80211R */	} else {		wpa_printf(MSG_DEBUG, "WPA: Could not get PMK");	}	sm->req_replay_counter_used = 0;	/* IEEE 802.11i does not set keyRun to FALSE, but not doing this	 * will break reauthentication since EAPOL state machines may not be	 * get into AUTHENTICATING state that clears keyRun before WPA state	 * machine enters AUTHENTICATION2 state and goes immediately to INITPMK	 * state and takes PMK from the previously used AAA Key. This will	 * eventually fail in 4-Way Handshake because Supplicant uses PMK	 * derived from the new AAA Key. Setting keyRun = FALSE here seems to	 * be good workaround for this issue. */	wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyRun, 0);}SM_STATE(WPA_PTK, INITPSK){	const u8 *psk;	SM_ENTRY_MA(WPA_PTK, INITPSK, wpa_ptk);	psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, NULL);	if (psk) {		os_memcpy(sm->PMK, psk, PMK_LEN);#ifdef CONFIG_IEEE80211R		os_memcpy(sm->xxkey, psk, PMK_LEN);		sm->xxkey_len = PMK_LEN;#endif /* CONFIG_IEEE80211R */	}	sm->req_replay_counter_used = 0;}SM_STATE(WPA_PTK, PTKSTART){	u8 buf[2 + RSN_SELECTOR_LEN + PMKID_LEN], *pmkid = NULL;	size_t pmkid_len = 0;	SM_ENTRY_MA(WPA_PTK, PTKSTART, wpa_ptk);	sm->PTKRequest = FALSE;	sm->TimeoutEvt = FALSE;	sm->TimeoutCtr++;	if (sm->TimeoutCtr > (int) dot11RSNAConfigPairwiseUpdateCount) {		/* No point in sending the EAPOL-Key - we will disconnect		 * immediately following this. */		return;	}	wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,			"sending 1/4 msg of 4-Way Handshake");	/*	 * TODO: Could add PMKID even with WPA2-PSK, but only if there is only	 * one possible PSK for this STA.	 */	if (sm->wpa == WPA_VERSION_WPA2 &&	    wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt)) {		pmkid = buf;		pmkid_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN;		pmkid[0] = WLAN_EID_VENDOR_SPECIFIC;		pmkid[1] = RSN_SELECTOR_LEN + PMKID_LEN;		RSN_SELECTOR_PUT(&pmkid[2], RSN_KEY_DATA_PMKID);		if (sm->pmksa)			os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN],				  sm->pmksa->pmkid, PMKID_LEN);		else {			/*			 * Calculate PMKID since no PMKSA cache entry was			 * available with pre-calculated PMKID.			 */			rsn_pmkid(sm->PMK, PMK_LEN, sm->wpa_auth->addr,				  sm->addr, &pmkid[2 + RSN_SELECTOR_LEN],				  wpa_key_mgmt_sha256(sm->wpa_key_mgmt));		}	}	wpa_send_eapol(sm->wpa_auth, sm,		       WPA_KEY_INFO_ACK | WPA_KEY_INFO_KEY_TYPE, NULL,		       sm->ANonce, pmkid, pmkid_len, 0, 0);}static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *pmk,			  struct wpa_ptk *ptk){#ifdef CONFIG_IEEE80211R	if (wpa_key_mgmt_ft(sm->wpa_key_mgmt))		return wpa_auth_derive_ptk_ft(sm, pmk, ptk);#endif /* CONFIG_IEEE80211R */	wpa_pmk_to_ptk(pmk, PMK_LEN, "Pairwise key expansion",		       sm->wpa_auth->addr, sm->addr, sm->ANonce, sm->SNonce,		       (u8 *) ptk, sizeof(*ptk),		       wpa_key_mgmt_sha256(sm->wpa_key_mgmt));	return 0;}SM_STATE(WPA_PTK, PTKCALCNEGOTIATING){	struct wpa_ptk PTK;	int ok = 0;	const u8 *pmk = NULL;	SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING, wpa_ptk);	sm->EAPOLKeyReceived = FALSE;	/* WPA with IEEE 802.1X: use the derived PMK from EAP	 * WPA-PSK: iterate through possible PSKs and select the one matching	 * the packet */	for (;;) {		if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) {			pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, pmk);			if (pmk == NULL)				break;		} else			pmk = sm->PMK;		wpa_derive_ptk(sm, pmk, &PTK);		if (wpa_verify_key_mic(&PTK, sm->last_rx_eapol_key,				       sm->last_rx_eapol_key_len) == 0) {			ok = 1;			break;		}		if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt))			break;	}	if (!ok) {		wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,				"invalid MIC in msg 2/4 of 4-Way Handshake");		return;	}	eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm);	if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) {		/* PSK may have changed from the previous choice, so update		 * state machine data based on whatever PSK was selected here.		 */		os_memcpy(sm->PMK, pmk, PMK_LEN);	}	sm->MICVerified = TRUE;	os_memcpy(&sm->PTK, &PTK, sizeof(PTK));	sm->PTK_valid = TRUE;

⌨️ 快捷键说明

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