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

📄 wpa_ft.c

📁 最新的Host AP 新添加了许多pcmcia 的驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * WPA Supplicant - IEEE 802.11r - Fast BSS Transition * Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */#include "includes.h"#include "common.h"#include "wpa.h"#include "wpa_i.h"#include "wpa_ie.h"#include "aes_wrap.h"#include "ieee802_11_defs.h"#ifdef CONFIG_IEEE80211Rint wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr,		      const struct wpa_eapol_key *key,		      struct wpa_ptk *ptk){	u8 pmk_r1_name[WPA_PMK_NAME_LEN];	u8 ptk_name[WPA_PMK_NAME_LEN];	const u8 *anonce = key->key_nonce;	if (sm->xxkey_len == 0) {		wpa_printf(MSG_DEBUG, "FT: XXKey not available for key "			   "derivation");		return -1;	}	wpa_derive_pmk_r0(sm->xxkey, sm->xxkey_len, sm->ssid,			  sm->ssid_len, sm->mobility_domain,			  sm->r0kh_id, sm->r0kh_id_len, sm->own_addr,			  sm->pmk_r0, sm->pmk_r0_name);	wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", sm->pmk_r0, PMK_LEN);	wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name",		    sm->pmk_r0_name, WPA_PMK_NAME_LEN);	wpa_derive_pmk_r1(sm->pmk_r0, sm->pmk_r0_name, sm->r1kh_id,			  sm->own_addr, sm->pmk_r1, pmk_r1_name);	wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", sm->pmk_r1, PMK_LEN);	wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", pmk_r1_name, WPA_PMK_NAME_LEN);	wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->snonce, anonce, sm->own_addr,			  sm->bssid, pmk_r1_name,			  (u8 *) ptk, sizeof(*ptk), ptk_name);	wpa_hexdump_key(MSG_DEBUG, "FT: PTK", (u8 *) ptk, sizeof(*ptk));	wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN);	return 0;}/** * wpa_sm_set_ft_params - Set FT (IEEE 802.11r) parameters * @sm: Pointer to WPA state machine data from wpa_sm_init() * @mobility_domain: Mobility domain identifier (2 octets) * @r0kh_id: PMK-R0 key holder identity (1-48 octets) * @r0kh_id_len: R0KH-ID length (1-48) * @r1kh_id: PMK-R1 key holder identity (16 octets) * Returns: 0 on success, -1 on failure */int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *mobility_domain,			 const u8 *r0kh_id, size_t r0kh_id_len,			 const u8 *r1kh_id){	if (sm && mobility_domain) {		wpa_hexdump(MSG_DEBUG, "FT: Mobility domain",			    mobility_domain, MOBILITY_DOMAIN_ID_LEN);		os_memcpy(sm->mobility_domain, mobility_domain,			  MOBILITY_DOMAIN_ID_LEN);	} else if (sm)		os_memset(sm->mobility_domain, 0, MOBILITY_DOMAIN_ID_LEN);	if (sm && r0kh_id) {		if (r0kh_id_len > FT_R0KH_ID_MAX_LEN)			return -1;		wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID", r0kh_id, r0kh_id_len);		os_memcpy(sm->r0kh_id, r0kh_id, r0kh_id_len);		sm->r0kh_id_len = r0kh_id_len;	} else if (sm) {		/* FIX: When should R0KH-ID be cleared? We need to keep the		 * old R0KH-ID in order to be able to use this during FT. */		/*		 * os_memset(sm->r0kh_id, 0, FT_R0KH_ID_LEN);		 * sm->r0kh_id_len = 0;		 */	}	if (sm && r1kh_id) {		wpa_hexdump(MSG_DEBUG, "FT: R1KH-ID", r1kh_id, FT_R1KH_ID_LEN);		os_memcpy(sm->r1kh_id, r1kh_id, FT_R1KH_ID_LEN);	} else if (sm)		os_memset(sm->r1kh_id, 0, FT_R1KH_ID_LEN);	return 0;}/** * wpa_ft_gen_req_ies - Generate FT (IEEE 802.11r) IEs for Auth Request * @sm: Pointer to WPA state machine data from wpa_sm_init() * @len: Buffer for returning the length of the IEs * @anonce: ANonce or %NULL if not yet available * @pmk_name: PMKR0Name or PMKR1Name to be added into the RSN IE PMKID List * @kck: 128-bit KCK for MIC or %NULL if no MIC is used * @target_ap: Target AP address * Returns: Pointer to buffer with IEs or %NULL on failure * * Caller is responsible for freeing the returned buffer with os_free(); */static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,			       const u8 *anonce, const u8 *pmk_name,			       const u8 *kck, const u8 *target_ap){	size_t buf_len;	u8 *buf, *pos, *ftie_len, *ftie_pos;	struct rsn_mdie *mdie;	struct rsn_ftie *ftie;	struct rsn_ie_hdr *rsnie;	u16 capab;	sm->ft_completed = 0;	buf_len = 2 + sizeof(struct rsn_mdie) + 2 + sizeof(struct rsn_ftie) +		2 + sm->r0kh_id_len + 100;	buf = os_zalloc(buf_len);	if (buf == NULL)		return NULL;	pos = buf;	/* RSNIE[PMKR0Name] */	rsnie = (struct rsn_ie_hdr *) pos;	rsnie->elem_id = WLAN_EID_RSN;	WPA_PUT_LE16(rsnie->version, RSN_VERSION);	pos = (u8 *) (rsnie + 1);	/* Group Suite Selector */	if (sm->group_cipher == WPA_CIPHER_CCMP)		RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);	else if (sm->group_cipher == WPA_CIPHER_TKIP)		RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP);	else {		wpa_printf(MSG_WARNING, "FT: Invalid group cipher (%d)",			   sm->group_cipher);		os_free(buf);		return NULL;	}	pos += RSN_SELECTOR_LEN;	/* Pairwise Suite Count */	WPA_PUT_LE16(pos, 1);	pos += 2;	/* Pairwise Suite List */	if (sm->pairwise_cipher == WPA_CIPHER_CCMP)		RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);	else if (sm->pairwise_cipher == WPA_CIPHER_TKIP)		RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP);	else {		wpa_printf(MSG_WARNING, "FT: Invalid pairwise cipher (%d)",			   sm->pairwise_cipher);		os_free(buf);		return NULL;	}	pos += RSN_SELECTOR_LEN;	/* Authenticated Key Management Suite Count */	WPA_PUT_LE16(pos, 1);	pos += 2;	/* Authenticated Key Management Suite List */	if (sm->key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X)		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X);	else if (sm->key_mgmt == WPA_KEY_MGMT_FT_PSK)		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK);	else {		wpa_printf(MSG_WARNING, "FT: Invalid key management type (%d)",			   sm->key_mgmt);		os_free(buf);		return NULL;	}	pos += RSN_SELECTOR_LEN;	/* RSN Capabilities */	capab = 0;#ifdef CONFIG_IEEE80211W	if (sm->mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC)		capab |= WPA_CAPABILITY_MFPC;#endif /* CONFIG_IEEE80211W */	WPA_PUT_LE16(pos, capab);	pos += 2;	/* PMKID Count */	WPA_PUT_LE16(pos, 1);	pos += 2;	/* PMKID List [PMKR0Name/PMKR1Name] */	os_memcpy(pos, pmk_name, WPA_PMK_NAME_LEN);	pos += WPA_PMK_NAME_LEN;#ifdef CONFIG_IEEE80211W	if (sm->mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) {		/* Management Group Cipher Suite */		RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);		pos += RSN_SELECTOR_LEN;	}#endif /* CONFIG_IEEE80211W */	rsnie->len = (pos - (u8 *) rsnie) - 2;	/* MDIE */	*pos++ = WLAN_EID_MOBILITY_DOMAIN;	*pos++ = sizeof(*mdie);	mdie = (struct rsn_mdie *) pos;	pos += sizeof(*mdie);	os_memcpy(mdie->mobility_domain, sm->mobility_domain,		  MOBILITY_DOMAIN_ID_LEN);	mdie->ft_capab = 0; /* FIX: copy from the target AP's MDIE */	/* FTIE[SNonce, R0KH-ID] */	ftie_pos = pos;	*pos++ = WLAN_EID_FAST_BSS_TRANSITION;	ftie_len = pos++;	ftie = (struct rsn_ftie *) pos;	pos += sizeof(*ftie);	os_memcpy(ftie->snonce, sm->snonce, WPA_NONCE_LEN);	if (anonce)		os_memcpy(ftie->anonce, anonce, WPA_NONCE_LEN);	/* R0KH-ID sub-element */	*pos++ = FTIE_SUBELEM_R0KH_ID;	*pos++ = sm->r0kh_id_len;	os_memcpy(pos, sm->r0kh_id, sm->r0kh_id_len);	pos += sm->r0kh_id_len;	*ftie_len = pos - ftie_len - 1;	if (kck) {		/*		 * IEEE Std 802.11r-2008, 11A.8.4		 * MIC shall be calculated over:		 * non-AP STA MAC address		 * Target AP MAC address		 * Transaction seq number (5 for ReassocReq, 3 otherwise)		 * RSN IE		 * MDIE		 * FTIE (with MIC field set to 0)		 * RIC-Request (if present)		 */		ftie->mic_control[1] = 3; /* Information element count */		if (wpa_ft_mic(kck, sm->own_addr, target_ap, 5,			       ((u8 *) mdie) - 2, 2 + sizeof(*mdie),			       ftie_pos, 2 + *ftie_len,			       (u8 *) rsnie, 2 + rsnie->len, NULL, 0,			       ftie->mic) < 0) {			wpa_printf(MSG_INFO, "FT: Failed to calculate MIC");			os_free(buf);			return NULL;		}	}	*len = pos - buf;	return buf;}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;	const u8 *tie;	size_t tie_len;	const u8 *igtk;	size_t igtk_len;};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;#ifdef CONFIG_IEEE80211W		case FTIE_SUBELEM_IGTK:			parse->igtk = pos + 2;			parse->igtk_len = pos[1];			break;#endif /* CONFIG_IEEE80211W */		}		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;		case WLAN_EID_TIMEOUT_INTERVAL:			parse->tie = pos + 2;			parse->tie_len = pos[1];			break;		}		pos += 2 + pos[1];	}	return 0;}static int wpa_ft_install_ptk(struct wpa_sm *sm, const u8 *bssid){	int keylen;	wpa_alg alg;	u8 null_rsc[6] = { 0, 0, 0, 0, 0, 0 };	wpa_printf(MSG_DEBUG, "FT: Installing PTK to the driver.");	switch (sm->pairwise_cipher) {	case WPA_CIPHER_CCMP:		alg = WPA_ALG_CCMP;		keylen = 16;		break;	case WPA_CIPHER_TKIP:		alg = WPA_ALG_TKIP;		keylen = 32;		break;	default:		wpa_printf(MSG_WARNING, "FT: Unsupported pairwise cipher %d",			   sm->pairwise_cipher);		return -1;	}	if (wpa_sm_set_key(sm, alg, bssid, 0, 1, null_rsc,			   sizeof(null_rsc), (u8 *) sm->ptk.tk1, keylen) < 0) {		wpa_printf(MSG_WARNING, "FT: Failed to set PTK to the driver");		return -1;	}	return 0;}/** * wpa_ft_prepare_auth_request - Generate over-the-air auth request * @sm: Pointer to WPA state machine data from wpa_sm_init() * Returns: 0 on success, -1 on failure */int wpa_ft_prepare_auth_request(struct wpa_sm *sm){	u8 *ft_ies;	size_t ft_ies_len;	/* Generate a new SNonce */

⌨️ 快捷键说明

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