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

📄 wpa_ft.c

📁 最新的Host AP 新添加了许多pcmcia 的驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * hostapd - IEEE 802.11r - Fast BSS Transition * Copyright (c) 2004-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 "config.h"#include "wpa.h"#include "aes_wrap.h"#include "ieee802_11.h"#include "defs.h"#include "wpa_auth_i.h"#include "wpa_auth_ie.h"#ifdef CONFIG_IEEE80211Rstatic int wpa_ft_rrb_send(struct wpa_authenticator *wpa_auth, const u8 *dst,			   const u8 *data, size_t data_len){	if (wpa_auth->cb.send_ether == NULL)		return -1;	return wpa_auth->cb.send_ether(wpa_auth->cb.ctx, dst, ETH_P_RRB,				       data, data_len);}static int wpa_ft_action_send(struct wpa_authenticator *wpa_auth,			      const u8 *dst, const u8 *data, size_t data_len){	if (wpa_auth->cb.send_ft_action == NULL)		return -1;	return wpa_auth->cb.send_ft_action(wpa_auth->cb.ctx, dst,					   data, data_len);}static struct wpa_state_machine *wpa_ft_add_sta(struct wpa_authenticator *wpa_auth, const u8 *sta_addr){	if (wpa_auth->cb.add_sta == NULL)		return NULL;	return wpa_auth->cb.add_sta(wpa_auth->cb.ctx, sta_addr);}int wpa_write_mdie(struct wpa_auth_config *conf, u8 *buf, size_t len){	u8 *pos = buf;	u8 capab;	if (len < 2 + sizeof(struct rsn_mdie))		return -1;	*pos++ = WLAN_EID_MOBILITY_DOMAIN;	*pos++ = MOBILITY_DOMAIN_ID_LEN + 1;	os_memcpy(pos, conf->mobility_domain, MOBILITY_DOMAIN_ID_LEN);	pos += MOBILITY_DOMAIN_ID_LEN;	capab = RSN_FT_CAPAB_FT_OVER_DS;	*pos++ = capab;	return pos - buf;}static int wpa_write_ftie(struct wpa_auth_config *conf, const u8 *r0kh_id,			  size_t r0kh_id_len,			  const u8 *anonce, const u8 *snonce,			  u8 *buf, size_t len, const u8 *subelem,			  size_t subelem_len){	u8 *pos = buf, *ielen;	struct rsn_ftie *hdr;	if (len < 2 + sizeof(*hdr) + 2 + FT_R1KH_ID_LEN + 2 + r0kh_id_len +	    subelem_len)		return -1;	*pos++ = WLAN_EID_FAST_BSS_TRANSITION;	ielen = pos++;	hdr = (struct rsn_ftie *) pos;	os_memset(hdr, 0, sizeof(*hdr));	pos += sizeof(*hdr);	WPA_PUT_LE16(hdr->mic_control, 0);	if (anonce)		os_memcpy(hdr->anonce, anonce, WPA_NONCE_LEN);	if (snonce)		os_memcpy(hdr->snonce, snonce, WPA_NONCE_LEN);	/* Optional Parameters */	*pos++ = FTIE_SUBELEM_R1KH_ID;	*pos++ = FT_R1KH_ID_LEN;	os_memcpy(pos, conf->r1_key_holder, FT_R1KH_ID_LEN);	pos += FT_R1KH_ID_LEN;	if (r0kh_id) {		*pos++ = FTIE_SUBELEM_R0KH_ID;		*pos++ = r0kh_id_len;		os_memcpy(pos, r0kh_id, r0kh_id_len);		pos += r0kh_id_len;	}	if (subelem) {		os_memcpy(pos, subelem, subelem_len);		pos += subelem_len;	}	*ielen = pos - buf - 2;	return pos - buf;}struct wpa_ft_pmk_r0_sa {	struct wpa_ft_pmk_r0_sa *next;	u8 pmk_r0[PMK_LEN];	u8 pmk_r0_name[WPA_PMK_NAME_LEN];	u8 spa[ETH_ALEN];	/* TODO: expiration, identity, radius_class, EAP type, VLAN ID */	int pmk_r1_pushed;};struct wpa_ft_pmk_r1_sa {	struct wpa_ft_pmk_r1_sa *next;	u8 pmk_r1[PMK_LEN];	u8 pmk_r1_name[WPA_PMK_NAME_LEN];	u8 spa[ETH_ALEN];	/* TODO: expiration, identity, radius_class, EAP type, VLAN ID */};struct wpa_ft_pmk_cache {	struct wpa_ft_pmk_r0_sa *pmk_r0;	struct wpa_ft_pmk_r1_sa *pmk_r1;};struct wpa_ft_pmk_cache * wpa_ft_pmk_cache_init(void){	struct wpa_ft_pmk_cache *cache;	cache = os_zalloc(sizeof(*cache));	return cache;}void wpa_ft_pmk_cache_deinit(struct wpa_ft_pmk_cache *cache){	struct wpa_ft_pmk_r0_sa *r0, *r0prev;	struct wpa_ft_pmk_r1_sa *r1, *r1prev;	r0 = cache->pmk_r0;	while (r0) {		r0prev = r0;		r0 = r0->next;		os_memset(r0prev->pmk_r0, 0, PMK_LEN);		os_free(r0prev);	}	r1 = cache->pmk_r1;	while (r1) {		r1prev = r1;		r1 = r1->next;		os_memset(r1prev->pmk_r1, 0, PMK_LEN);		os_free(r1prev);	}	os_free(cache);}static int wpa_ft_store_pmk_r0(struct wpa_authenticator *wpa_auth,			       const u8 *spa, const u8 *pmk_r0,			       const u8 *pmk_r0_name){	struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache;	struct wpa_ft_pmk_r0_sa *r0;	/* TODO: add expiration and limit on number of entries in cache */	r0 = os_zalloc(sizeof(*r0));	if (r0 == NULL)		return -1;	os_memcpy(r0->pmk_r0, pmk_r0, PMK_LEN);	os_memcpy(r0->pmk_r0_name, pmk_r0_name, WPA_PMK_NAME_LEN);	os_memcpy(r0->spa, spa, ETH_ALEN);	r0->next = cache->pmk_r0;	cache->pmk_r0 = r0;	return 0;}static int wpa_ft_fetch_pmk_r0(struct wpa_authenticator *wpa_auth,			       const u8 *spa, const u8 *pmk_r0_name,			       u8 *pmk_r0){	struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache;	struct wpa_ft_pmk_r0_sa *r0;	r0 = cache->pmk_r0;	while (r0) {		if (os_memcmp(r0->spa, spa, ETH_ALEN) == 0 &&		    os_memcmp(r0->pmk_r0_name, pmk_r0_name, WPA_PMK_NAME_LEN)		    == 0) {			os_memcpy(pmk_r0, r0->pmk_r0, PMK_LEN);			return 0;		}		r0 = r0->next;	}	return -1;}static int wpa_ft_store_pmk_r1(struct wpa_authenticator *wpa_auth,			       const u8 *spa, const u8 *pmk_r1,			       const u8 *pmk_r1_name){	struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache;	struct wpa_ft_pmk_r1_sa *r1;	/* TODO: add expiration and limit on number of entries in cache */	r1 = os_zalloc(sizeof(*r1));	if (r1 == NULL)		return -1;	os_memcpy(r1->pmk_r1, pmk_r1, PMK_LEN);	os_memcpy(r1->pmk_r1_name, pmk_r1_name, WPA_PMK_NAME_LEN);	os_memcpy(r1->spa, spa, ETH_ALEN);	r1->next = cache->pmk_r1;	cache->pmk_r1 = r1;	return 0;}static int wpa_ft_fetch_pmk_r1(struct wpa_authenticator *wpa_auth,			       const u8 *spa, const u8 *pmk_r1_name,			       u8 *pmk_r1){	struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache;	struct wpa_ft_pmk_r1_sa *r1;	r1 = cache->pmk_r1;	while (r1) {		if (os_memcmp(r1->spa, spa, ETH_ALEN) == 0 &&		    os_memcmp(r1->pmk_r1_name, pmk_r1_name, WPA_PMK_NAME_LEN)		    == 0) {			os_memcpy(pmk_r1, r1->pmk_r1, PMK_LEN);			return 0;		}		r1 = r1->next;	}	return -1;}static int wpa_ft_pull_pmk_r1(struct wpa_authenticator *wpa_auth,			      const u8 *s1kh_id, const u8 *r0kh_id,			      size_t r0kh_id_len, const u8 *pmk_r0_name){	struct ft_remote_r0kh *r0kh;	struct ft_r0kh_r1kh_pull_frame frame, f;	r0kh = wpa_auth->conf.r0kh_list;	while (r0kh) {		if (r0kh->id_len == r0kh_id_len &&		    os_memcmp(r0kh->id, r0kh_id, r0kh_id_len) == 0)			break;		r0kh = r0kh->next;	}	if (r0kh == NULL)		return -1;	wpa_printf(MSG_DEBUG, "FT: Send PMK-R1 pull request to remote R0KH "		   "address " MACSTR, MAC2STR(r0kh->addr));	os_memset(&frame, 0, sizeof(frame));	frame.frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB;	frame.packet_type = FT_PACKET_R0KH_R1KH_PULL;	frame.data_length = host_to_le16(FT_R0KH_R1KH_PULL_DATA_LEN);	os_memcpy(frame.ap_address, wpa_auth->addr, ETH_ALEN);	/* aes_wrap() does not support inplace encryption, so use a temporary	 * buffer for the data. */	if (os_get_random(f.nonce, sizeof(f.nonce))) {		wpa_printf(MSG_DEBUG, "FT: Failed to get random data for "			   "nonce");		return -1;	}	os_memcpy(f.pmk_r0_name, pmk_r0_name, WPA_PMK_NAME_LEN);	os_memcpy(f.r1kh_id, wpa_auth->conf.r1_key_holder, FT_R1KH_ID_LEN);	os_memcpy(f.s1kh_id, s1kh_id, ETH_ALEN);	if (aes_wrap(r0kh->key, (FT_R0KH_R1KH_PULL_DATA_LEN + 7) / 8,		     f.nonce, frame.nonce) < 0)		return -1;	wpa_ft_rrb_send(wpa_auth, r0kh->addr, (u8 *) &frame, sizeof(frame));	return 0;}int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk,			   struct wpa_ptk *ptk){	u8 pmk_r0[PMK_LEN], pmk_r0_name[WPA_PMK_NAME_LEN];	u8 pmk_r1[PMK_LEN], pmk_r1_name[WPA_PMK_NAME_LEN];	u8 ptk_name[WPA_PMK_NAME_LEN];	const u8 *mdid = sm->wpa_auth->conf.mobility_domain;	const u8 *r0kh = sm->wpa_auth->conf.r0_key_holder;	size_t r0kh_len = sm->wpa_auth->conf.r0_key_holder_len;	const u8 *r1kh = sm->wpa_auth->conf.r1_key_holder;	const u8 *ssid = sm->wpa_auth->conf.ssid;	size_t ssid_len = sm->wpa_auth->conf.ssid_len;	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, ssid, ssid_len, mdid,			  r0kh, r0kh_len, sm->addr, pmk_r0, pmk_r0_name);	wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", pmk_r0, PMK_LEN);	wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name", pmk_r0_name, WPA_PMK_NAME_LEN);	wpa_ft_store_pmk_r0(sm->wpa_auth, sm->addr, pmk_r0, pmk_r0_name);	wpa_derive_pmk_r1(pmk_r0, pmk_r0_name, r1kh, sm->addr,			  pmk_r1, pmk_r1_name);	wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", pmk_r1, PMK_LEN);	wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", pmk_r1_name, WPA_PMK_NAME_LEN);	wpa_ft_store_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1, pmk_r1_name);	wpa_pmk_r1_to_ptk(pmk_r1, sm->SNonce, sm->ANonce, sm->addr,			  sm->wpa_auth->addr, 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;}static inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth,				      const u8 *addr, int idx, u8 *seq){	if (wpa_auth->cb.get_seqnum == NULL)		return -1;	return wpa_auth->cb.get_seqnum(wpa_auth->cb.ctx, addr, idx, seq);}#ifdef CONFIG_IEEE80211Wstatic inline int wpa_auth_get_seqnum_igtk(struct wpa_authenticator *wpa_auth,					   const u8 *addr, int idx, u8 *seq){	if (wpa_auth->cb.get_seqnum_igtk == NULL)		return -1;	return wpa_auth->cb.get_seqnum_igtk(wpa_auth->cb.ctx, addr, idx, seq);}#endif /* CONFIG_IEEE80211W */static u8 * wpa_ft_gtk_subelem(struct wpa_state_machine *sm, size_t *len){	u8 *subelem;	struct wpa_group *gsm = sm->group;	size_t subelem_len, pad_len;	const u8 *key;	size_t key_len;	u8 keybuf[32];	key_len = gsm->GTK_len;	if (key_len > sizeof(keybuf))		return NULL;	/*	 * Pad key for AES Key Wrap if it is not multiple of 8 bytes or is less	 * than 16 bytes.	 */	pad_len = key_len % 8;	if (pad_len)		pad_len = 8 - pad_len;	if (key_len + pad_len < 16)		pad_len += 8;	if (pad_len) {		os_memcpy(keybuf, gsm->GTK[gsm->GN - 1], key_len);		os_memset(keybuf + key_len, 0, pad_len);		keybuf[key_len] = 0xdd;		key_len += pad_len;		key = keybuf;	} else		key = gsm->GTK[gsm->GN - 1];	/*	 * Sub-elem ID[1] | Length[1] | Key Info[1] | Key Length[1] | RSC[8] |	 * Key[5..32].	 */	subelem_len = 12 + key_len + 8;	subelem = os_zalloc(subelem_len);	if (subelem == NULL)		return NULL;	subelem[0] = FTIE_SUBELEM_GTK;	subelem[1] = 10 + key_len + 8;	subelem[2] = gsm->GN & 0x03; /* Key ID in B0-B1 of Key Info */	subelem[3] = gsm->GTK_len;	wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, subelem + 4);	if (aes_wrap(sm->PTK.kek, key_len / 8, key, subelem + 12)) {		os_free(subelem);		return NULL;	}	*len = subelem_len;	return subelem;}#ifdef CONFIG_IEEE80211Wstatic u8 * wpa_ft_igtk_subelem(struct wpa_state_machine *sm, size_t *len){	u8 *subelem, *pos;	struct wpa_group *gsm = sm->group;	size_t subelem_len;	/* Sub-elem ID[1] | Length[1] | KeyID[2] | IPN[6] | Key Length[1] |	 * Key[16+8] */	subelem_len = 1 + 1 + 2 + 6 + 1 + WPA_IGTK_LEN + 8;	subelem = os_zalloc(subelem_len);	if (subelem == NULL)		return NULL;	pos = subelem;	*pos++ = FTIE_SUBELEM_IGTK;	*pos++ = subelem_len - 2;	WPA_PUT_LE16(pos, gsm->GN_igtk);	pos += 2;	wpa_auth_get_seqnum_igtk(sm->wpa_auth, NULL, gsm->GN_igtk, pos);	pos += 6;	*pos++ = WPA_IGTK_LEN;	if (aes_wrap(sm->PTK.kek, WPA_IGTK_LEN / 8,		     gsm->IGTK[gsm->GN_igtk - 4], pos)) {		os_free(subelem);		return NULL;	}	*len = subelem_len;	return subelem;}#endif /* CONFIG_IEEE80211W */u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,				 size_t max_len, int auth_alg){	u8 *end, *mdie, *ftie, *rsnie, *r0kh_id, *subelem = NULL;	size_t mdie_len, ftie_len, rsnie_len, r0kh_id_len, subelem_len = 0;	int res;	struct wpa_auth_config *conf;	struct rsn_ftie *_ftie;	if (sm == NULL)		return pos;	conf = &sm->wpa_auth->conf;	if (sm->wpa_key_mgmt != WPA_KEY_MGMT_FT_IEEE8021X &&	    sm->wpa_key_mgmt != WPA_KEY_MGMT_FT_PSK)		return pos;	end = pos + max_len;	/* RSN */	res = wpa_write_rsn_ie(conf, pos, end - pos, sm->pmk_r1_name);	if (res < 0)		return pos;	rsnie = pos;	rsnie_len = res;	pos += res;

⌨️ 快捷键说明

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