wpa_ft.c

来自「最新的Host AP 新添加了许多pcmcia 的驱动」· C语言 代码 · 共 1,500 行 · 第 1/3 页

C
1,500
字号
	/* Mobility Domain Information */	res = wpa_write_mdie(conf, pos, end - pos);	if (res < 0)		return pos;	mdie = pos;	mdie_len = res;	pos += res;	/* Fast BSS Transition Information */	if (auth_alg == WLAN_AUTH_FT) {		subelem = wpa_ft_gtk_subelem(sm, &subelem_len);		r0kh_id = sm->r0kh_id;		r0kh_id_len = sm->r0kh_id_len;#ifdef CONFIG_IEEE80211W		if (sm->mgmt_frame_prot) {			u8 *igtk;			size_t igtk_len;			u8 *nbuf;			igtk = wpa_ft_igtk_subelem(sm, &igtk_len);			if (igtk == NULL) {				os_free(subelem);				return pos;			}			nbuf = os_realloc(subelem, subelem_len + igtk_len);			if (nbuf == NULL) {				os_free(subelem);				os_free(igtk);				return pos;			}			subelem = nbuf;			os_memcpy(subelem + subelem_len, igtk, igtk_len);			subelem_len += igtk_len;			os_free(igtk);		}#endif /* CONFIG_IEEE80211W */	} else {		r0kh_id = conf->r0_key_holder;		r0kh_id_len = conf->r0_key_holder_len;	}	res = wpa_write_ftie(conf, r0kh_id, r0kh_id_len, NULL, NULL, pos,			     end - pos, subelem, subelem_len);	os_free(subelem);	if (res < 0)		return pos;	ftie = pos;	ftie_len = res;	pos += res;	_ftie = (struct rsn_ftie *) (ftie + 2);	_ftie->mic_control[1] = 3; /* Information element count */	if (wpa_ft_mic(sm->PTK.kck, sm->addr, sm->wpa_auth->addr, 6,		       mdie, mdie_len, ftie, ftie_len,		       rsnie, rsnie_len, NULL, 0, _ftie->mic) < 0)		wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC");	return pos;}struct wpa_ft_ies {	const u8 *mdie;	size_t mdie_len;	const u8 *ftie;	size_t ftie_len;	const u8 *r1kh_id;	const u8 *gtk;	size_t gtk_len;	const u8 *r0kh_id;	size_t r0kh_id_len;	const u8 *rsn;	size_t rsn_len;	const u8 *rsn_pmkid;};static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len,			     struct wpa_ft_ies *parse){	const u8 *end, *pos;	parse->ftie = ie;	parse->ftie_len = ie_len;	pos = ie + sizeof(struct rsn_ftie);	end = ie + ie_len;	while (pos + 2 <= end && pos + 2 + pos[1] <= end) {		switch (pos[0]) {		case FTIE_SUBELEM_R1KH_ID:			if (pos[1] != FT_R1KH_ID_LEN) {				wpa_printf(MSG_DEBUG, "FT: Invalid R1KH-ID "					   "length in FTIE: %d", pos[1]);				return -1;			}			parse->r1kh_id = pos + 2;			break;		case FTIE_SUBELEM_GTK:			parse->gtk = pos + 2;			parse->gtk_len = pos[1];			break;		case FTIE_SUBELEM_R0KH_ID:			if (pos[1] < 1 || pos[1] > FT_R0KH_ID_MAX_LEN) {				wpa_printf(MSG_DEBUG, "FT: Invalid R0KH-ID "					   "length in FTIE: %d", pos[1]);				return -1;			}			parse->r0kh_id = pos + 2;			parse->r0kh_id_len = pos[1];			break;		}		pos += 2 + pos[1];	}	return 0;}static int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,			    struct wpa_ft_ies *parse){	const u8 *end, *pos;	struct wpa_ie_data data;	int ret;	os_memset(parse, 0, sizeof(*parse));	if (ies == NULL)		return 0;	pos = ies;	end = ies + ies_len;	while (pos + 2 <= end && pos + 2 + pos[1] <= end) {		switch (pos[0]) {		case WLAN_EID_RSN:			parse->rsn = pos + 2;			parse->rsn_len = pos[1];			ret = wpa_parse_wpa_ie_rsn(parse->rsn - 2,						   parse->rsn_len + 2,						   &data);			if (ret < 0) {				wpa_printf(MSG_DEBUG, "FT: Failed to parse "					   "RSN IE: %d", ret);				return -1;			}			if (data.num_pmkid == 1 && data.pmkid)				parse->rsn_pmkid = data.pmkid;			break;		case WLAN_EID_MOBILITY_DOMAIN:			parse->mdie = pos + 2;			parse->mdie_len = pos[1];			break;		case WLAN_EID_FAST_BSS_TRANSITION:			if (wpa_ft_parse_ftie(pos + 2, pos[1], parse) < 0)				return -1;			break;		}		pos += 2 + pos[1];	}	return 0;}static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth,				   int vlan_id,				   const char *alg, const u8 *addr, int idx,				   u8 *key, size_t key_len){	if (wpa_auth->cb.set_key == NULL)		return -1;	return wpa_auth->cb.set_key(wpa_auth->cb.ctx, vlan_id, alg, addr, idx,				    key, key_len);}static void wpa_ft_install_ptk(struct wpa_state_machine *sm){	char *alg;	int klen;	/* MLME-SETKEYS.request(PTK) */	if (sm->pairwise == WPA_CIPHER_TKIP) {		alg = "TKIP";		klen = 32;	} else if (sm->pairwise == WPA_CIPHER_CCMP) {		alg = "CCMP";		klen = 16;	} else		return;	/* FIX: add STA entry to kernel/driver here? The set_key will fail	 * most likely without this.. At the moment, STA entry is added only	 * after association has been completed. Alternatively, could	 * re-configure PTK at that point(?).	 */	if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0,			     sm->PTK.tk1, klen))		return;	/* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */	sm->pairwise_set = TRUE;}static u16 wpa_ft_process_auth_req(struct wpa_state_machine *sm,				   const u8 *ies, size_t ies_len,				   u8 **resp_ies, size_t *resp_ies_len){	struct rsn_mdie *mdie;	struct rsn_ftie *ftie;	u8 pmk_r1[PMK_LEN], pmk_r1_name[WPA_PMK_NAME_LEN];	u8 ptk_name[WPA_PMK_NAME_LEN];	struct wpa_auth_config *conf;	struct wpa_ft_ies parse;	size_t buflen;	int ret;	u8 *pos, *end;	*resp_ies = NULL;	*resp_ies_len = 0;	sm->pmk_r1_name_valid = 0;	conf = &sm->wpa_auth->conf;	wpa_hexdump(MSG_DEBUG, "FT: Received authentication frame IEs",		    ies, ies_len);	if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) {		wpa_printf(MSG_DEBUG, "FT: Failed to parse FT IEs");		return WLAN_STATUS_UNSPECIFIED_FAILURE;	}	mdie = (struct rsn_mdie *) parse.mdie;	if (mdie == NULL || parse.mdie_len < sizeof(*mdie) ||	    os_memcmp(mdie->mobility_domain,		      sm->wpa_auth->conf.mobility_domain,		      MOBILITY_DOMAIN_ID_LEN) != 0) {		wpa_printf(MSG_DEBUG, "FT: Invalid MDIE");		return WLAN_STATUS_INVALID_MDIE;	}	ftie = (struct rsn_ftie *) parse.ftie;	if (ftie == NULL || parse.ftie_len < sizeof(*ftie)) {		wpa_printf(MSG_DEBUG, "FT: Invalid FTIE");		return WLAN_STATUS_INVALID_FTIE;	}	os_memcpy(sm->SNonce, ftie->snonce, WPA_NONCE_LEN);	if (parse.r0kh_id == NULL) {		wpa_printf(MSG_DEBUG, "FT: Invalid FTIE - no R0KH-ID");		return WLAN_STATUS_INVALID_FTIE;	}	wpa_hexdump(MSG_DEBUG, "FT: STA R0KH-ID",		    parse.r0kh_id, parse.r0kh_id_len);	os_memcpy(sm->r0kh_id, parse.r0kh_id, parse.r0kh_id_len);	sm->r0kh_id_len = parse.r0kh_id_len;	if (parse.rsn_pmkid == NULL) {		wpa_printf(MSG_DEBUG, "FT: No PMKID in RSNIE");		return WLAN_STATUS_INVALID_PMKID;	}	wpa_hexdump(MSG_DEBUG, "FT: Requested PMKR0Name",		    parse.rsn_pmkid, WPA_PMK_NAME_LEN);	wpa_derive_pmk_r1_name(parse.rsn_pmkid,			       sm->wpa_auth->conf.r1_key_holder, sm->addr,			       pmk_r1_name);	wpa_hexdump(MSG_DEBUG, "FT: Derived requested PMKR1Name",		    pmk_r1_name, WPA_PMK_NAME_LEN);	if (wpa_ft_fetch_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1_name, pmk_r1) <	    0) {		if (wpa_ft_pull_pmk_r1(sm->wpa_auth, sm->addr, sm->r0kh_id,				       sm->r0kh_id_len, parse.rsn_pmkid) < 0) {			wpa_printf(MSG_DEBUG, "FT: Did not have matching "				   "PMK-R1 and unknown R0KH-ID");			return WLAN_STATUS_INVALID_PMKID;		}		/*		 * TODO: Should return "status pending" (and the caller should		 * not send out response now). The real response will be sent		 * once the response from R0KH is received.		 */		return WLAN_STATUS_INVALID_PMKID;	}	wpa_hexdump_key(MSG_DEBUG, "FT: Selected PMK-R1", pmk_r1, PMK_LEN);	sm->pmk_r1_name_valid = 1;	os_memcpy(sm->pmk_r1_name, pmk_r1_name, WPA_PMK_NAME_LEN);	if (os_get_random(sm->ANonce, WPA_NONCE_LEN)) {		wpa_printf(MSG_DEBUG, "FT: Failed to get random data for "			   "ANonce");		return WLAN_STATUS_UNSPECIFIED_FAILURE;	}	wpa_hexdump(MSG_DEBUG, "FT: Received SNonce",		    sm->SNonce, WPA_NONCE_LEN);	wpa_hexdump(MSG_DEBUG, "FT: Generated ANonce",		    sm->ANonce, WPA_NONCE_LEN);	wpa_pmk_r1_to_ptk(pmk_r1, sm->SNonce, sm->ANonce, sm->addr,			  sm->wpa_auth->addr, pmk_r1_name,			  (u8 *) &sm->PTK, sizeof(sm->PTK), ptk_name);	wpa_hexdump_key(MSG_DEBUG, "FT: PTK",			(u8 *) &sm->PTK, sizeof(sm->PTK));	wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN);	wpa_ft_install_ptk(sm);	buflen = 2 + sizeof(struct rsn_mdie) + 2 + sizeof(struct rsn_ftie) +		2 + FT_R1KH_ID_LEN + 200;	*resp_ies = os_zalloc(buflen);	if (*resp_ies == NULL) {		return WLAN_STATUS_UNSPECIFIED_FAILURE;	}	pos = *resp_ies;	end = *resp_ies + buflen;	ret = wpa_write_rsn_ie(conf, pos, end - pos, parse.rsn_pmkid);	if (ret < 0) {		os_free(*resp_ies);		*resp_ies = NULL;		return WLAN_STATUS_UNSPECIFIED_FAILURE;	}	pos += ret;	ret = wpa_write_mdie(conf, pos, end - pos);	if (ret < 0) {		os_free(*resp_ies);		*resp_ies = NULL;		return WLAN_STATUS_UNSPECIFIED_FAILURE;	}	pos += ret;	ret = wpa_write_ftie(conf, parse.r0kh_id, parse.r0kh_id_len,			     sm->ANonce, sm->SNonce, pos, end - pos, NULL, 0);	if (ret < 0) {		os_free(*resp_ies);		*resp_ies = NULL;		return WLAN_STATUS_UNSPECIFIED_FAILURE;	}	pos += ret;	*resp_ies_len = pos - *resp_ies;	return WLAN_STATUS_SUCCESS;}void wpa_ft_process_auth(struct wpa_state_machine *sm, const u8 *bssid,			 u16 auth_transaction, const u8 *ies, size_t ies_len,			 void (*cb)(void *ctx, const u8 *dst, const u8 *bssid,				    u16 auth_transaction, u16 status,				    const u8 *ies, size_t ies_len),			 void *ctx){	u16 status;	u8 *resp_ies;	size_t resp_ies_len;	if (sm == NULL) {		wpa_printf(MSG_DEBUG, "FT: Received authentication frame, but "			   "WPA SM not available");		return;	}	wpa_printf(MSG_DEBUG, "FT: Received authentication frame: STA=" MACSTR		   " BSSID=" MACSTR " transaction=%d",		   MAC2STR(sm->addr), MAC2STR(bssid), auth_transaction);	status = wpa_ft_process_auth_req(sm, ies, ies_len, &resp_ies,					 &resp_ies_len);	wpa_printf(MSG_DEBUG, "FT: FT authentication response: dst=" MACSTR		   " auth_transaction=%d status=%d",		   MAC2STR(sm->addr), auth_transaction + 1, status);	wpa_hexdump(MSG_DEBUG, "FT: Response IEs", resp_ies, resp_ies_len);	cb(ctx, sm->addr, bssid, auth_transaction + 1, status,	   resp_ies, resp_ies_len);	os_free(resp_ies);}u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,			    size_t ies_len){	struct wpa_ft_ies parse;	struct rsn_mdie *mdie;	struct rsn_ftie *ftie;	u8 mic[16];	if (sm == NULL)		return WLAN_STATUS_UNSPECIFIED_FAILURE;	wpa_hexdump(MSG_DEBUG, "FT: Reassoc Req IEs", ies, ies_len);	if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) {		wpa_printf(MSG_DEBUG, "FT: Failed to parse FT IEs");		return WLAN_STATUS_UNSPECIFIED_FAILURE;	}	if (parse.rsn == NULL) {		wpa_printf(MSG_DEBUG, "FT: No RSNIE in Reassoc Req");		return WLAN_STATUS_UNSPECIFIED_FAILURE;	}	if (parse.rsn_pmkid == NULL) {		wpa_printf(MSG_DEBUG, "FT: No PMKID in RSNIE");		return WLAN_STATUS_INVALID_PMKID;	}	if (os_memcmp(parse.rsn_pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN) != 0)	{		wpa_printf(MSG_DEBUG, "FT: PMKID in Reassoc Req did not match "			   "with the PMKR1Name derived from auth request");		return WLAN_STATUS_INVALID_PMKID;	}	mdie = (struct rsn_mdie *) parse.mdie;	if (mdie == NULL || parse.mdie_len < sizeof(*mdie) ||	    os_memcmp(mdie->mobility_domain,		      sm->wpa_auth->conf.mobility_domain,		      MOBILITY_DOMAIN_ID_LEN) != 0) {		wpa_printf(MSG_DEBUG, "FT: Invalid MDIE");		return WLAN_STATUS_INVALID_MDIE;	}	ftie = (struct rsn_ftie *) parse.ftie;	if (ftie == NULL || parse.ftie_len < sizeof(*ftie)) {		wpa_printf(MSG_DEBUG, "FT: Invalid FTIE");		return WLAN_STATUS_INVALID_FTIE;	}	/*	 * Assume that MDIE, FTIE, and RSN IE are protected and that there is	 * no RIC, so total of 3 protected IEs.	 */	if (ftie->mic_control[1] != 3) {		wpa_printf(MSG_DEBUG, "FT: Unexpected IE count in FTIE (%d)",			   ftie->mic_control[1]);		return WLAN_STATUS_INVALID_FTIE;	}	if (wpa_ft_mic(sm->PTK.kck, sm->addr, sm->wpa_auth->addr, 5,		       parse.mdie - 2, parse.mdie_len + 2,		       parse.ftie - 2, parse.ftie_len + 2,		       parse.rsn - 2, parse.rsn_len + 2, NULL, 0,		       mic) < 0) {		wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC");		return WLAN_STATUS_UNSPECIFIED_FAILURE;	}	if (os_memcmp(mic, ftie->mic, 16) != 0) {		wpa_printf(MSG_DEBUG, "FT: Invalid MIC in FTIE");		wpa_hexdump(MSG_MSGDUMP, "FT: Received MIC", ftie->mic, 16);		wpa_hexdump(MSG_MSGDUMP, "FT: Calculated MIC", mic, 16);		return WLAN_STATUS_INVALID_FTIE;	}	return WLAN_STATUS_SUCCESS;}int wpa_ft_action_rx(struct wpa_state_machine *sm, const u8 *data, size_t len){	const u8 *sta_addr, *target_ap;	const u8 *ies;	size_t ies_len;	u8 action;	struct ft_rrb_frame *frame;	if (sm == NULL)		return -1;	/*	 * data: Category[1] Action[1] STA_Address[6] Target_AP_Address[6]	 * FT Request action frame body[variable]	 */	if (len < 14) {		wpa_printf(MSG_DEBUG, "FT: Too short FT Action frame "			   "(len=%lu)", (unsigned long) len);		return -1;	}	action = data[1];	sta_addr = data + 2;	target_ap = data + 8;	ies = data + 14;	ies_len = len - 14;	wpa_printf(MSG_DEBUG, "FT: Received FT Action frame (STA=" MACSTR		   " Target AP=" MACSTR " Action=%d)",		   MAC2STR(sta_addr), MAC2STR(target_ap), action);

⌨️ 快捷键说明

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