Beispiel #1
0
static int fst_session_send_tear_down(struct fst_session *s)
{
	struct fst_tear_down td;
	int res;

	if (!fst_session_is_in_progress(s)) {
		fst_printf_session(s, MSG_ERROR, "No FST setup to tear down");
		return -1;
	}

	WPA_ASSERT(s->data.old_iface != NULL);
	WPA_ASSERT(s->data.new_iface != NULL);

	os_memset(&td, 0, sizeof(td));

	td.action = FST_ACTION_TEAR_DOWN;
	td.fsts_id = host_to_le32(s->data.fsts_id);

	res = fst_session_send_action(s, TRUE, &td, sizeof(td), NULL);
	if (!res)
		fst_printf_sframe(s, TRUE, MSG_INFO, "FST TearDown sent");
	else
		fst_printf_sframe(s, TRUE, MSG_ERROR,
				  "failed to send FST TearDown");

	return res;
}
Beispiel #2
0
static int fst_session_send_action(struct fst_session *s, Boolean old_iface,
				   const void *payload, size_t size,
				   const struct wpabuf *extra_buf)
{
	size_t len;
	int res;
	struct wpabuf *buf;
	u8 action;
	struct fst_iface *iface =
		old_iface ? s->data.old_iface : s->data.new_iface;

	WPA_ASSERT(payload != NULL);
	WPA_ASSERT(size != 0);

	action = *(const u8 *) payload;

	WPA_ASSERT(action <= FST_ACTION_MAX_SUPPORTED);

	if (!iface) {
		fst_printf_session(s, MSG_ERROR,
				   "no %s interface for FST Action '%s' sending",
				   old_iface ? "old" : "new",
				   fst_action_names[action]);
		return -1;
	}

	len = sizeof(u8) /* category */ + size;
	if (extra_buf)
		len += wpabuf_size(extra_buf);

	buf = wpabuf_alloc(len);
	if (!buf) {
		fst_printf_session(s, MSG_ERROR,
				   "cannot allocate buffer of %zu bytes for FST Action '%s' sending",
				   len, fst_action_names[action]);
		return -1;
	}

	wpabuf_put_u8(buf, WLAN_ACTION_FST);
	wpabuf_put_data(buf, payload, size);
	if (extra_buf)
		wpabuf_put_buf(buf, extra_buf);

	res = fst_iface_send_action(iface,
				    old_iface ? s->data.old_peer_addr :
				    s->data.new_peer_addr, buf);
	if (res < 0)
		fst_printf_siface(s, iface, MSG_ERROR,
				  "failed to send FST Action '%s'",
				  fst_action_names[action]);
	else
		fst_printf_siface(s, iface, MSG_DEBUG, "FST Action '%s' sent",
				  fst_action_names[action]);
	wpabuf_free(buf);

	return res;
}
Beispiel #3
0
struct fst_iface * fst_attach(const char *ifname, const u8 *own_addr,
			      const struct fst_wpa_obj *iface_obj,
			      const struct fst_iface_cfg *cfg)
{
	struct fst_group *g;
	struct fst_group *group = NULL;
	struct fst_iface *iface = NULL;
	Boolean new_group = FALSE;

	WPA_ASSERT(ifname != NULL);
	WPA_ASSERT(iface_obj != NULL);
	WPA_ASSERT(cfg != NULL);

	foreach_fst_group(g) {
		if (os_strcmp(cfg->group_id, fst_group_get_id(g)) == 0) {
			group = g;
			break;
		}
	}

	if (!group) {
		group = fst_group_create(cfg->group_id);
		if (!group) {
			fst_printf(MSG_ERROR, "%s: FST group cannot be created",
				   cfg->group_id);
			return NULL;
		}
		new_group = TRUE;
	}

	iface = fst_iface_create(group, ifname, own_addr, iface_obj, cfg);
	if (!iface) {
		fst_printf_group(group, MSG_ERROR, "cannot create iface for %s",
				 ifname);
		if (new_group)
			fst_group_delete(group);
		return NULL;
	}

	fst_group_attach_iface(group, iface);
	fst_group_update_ie(group);

	foreach_fst_ctrl_call(on_iface_added, iface);

	fst_printf_iface(iface, MSG_DEBUG,
			 "iface attached to group %s (prio=%d, llt=%d)",
			 cfg->group_id, cfg->priority, cfg->llt);

	return iface;
}
Beispiel #4
0
void fst_session_handle_action(struct fst_session *s,
			       struct fst_iface *iface,
			       const struct ieee80211_mgmt *mgmt,
			       size_t frame_len)
{
	switch (mgmt->u.action.u.fst_action.action) {
	case FST_ACTION_SETUP_REQUEST:
		WPA_ASSERT(0);
		break;
	case FST_ACTION_SETUP_RESPONSE:
		fst_session_handle_setup_response(s, iface, mgmt, frame_len);
		break;
	case FST_ACTION_TEAR_DOWN:
		fst_session_handle_tear_down(s, iface, mgmt, frame_len);
		break;
	case FST_ACTION_ACK_REQUEST:
		fst_session_handle_ack_request(s, iface, mgmt, frame_len);
		break;
	case FST_ACTION_ACK_RESPONSE:
		fst_session_handle_ack_response(s, iface, mgmt, frame_len);
		break;
	case FST_ACTION_ON_CHANNEL_TUNNEL:
	default:
		fst_printf_sframe(s, FALSE, MSG_ERROR,
				  "Unsupported FST Action frame");
		break;
	}
}
int eap_server_tls_phase1(struct eap_sm *sm, struct eap_ssl_data *data)
{
	if (data->tls_out) {
		/* This should not happen.. */
		wpa_printf(MSG_INFO, "SSL: pending tls_out data when "
			   "processing new message");
		wpabuf_free(data->tls_out);
		WPA_ASSERT(data->tls_out == NULL);
	}

	data->tls_out = tls_connection_server_handshake(sm->ssl_ctx,
							data->conn,
							data->tls_in, NULL);
	if (data->tls_out == NULL) {
		wpa_printf(MSG_INFO, "SSL: TLS processing failed");
		return -1;
	}
	if (tls_connection_get_failed(sm->ssl_ctx, data->conn)) {
		/* TLS processing has failed - return error */
		wpa_printf(MSG_DEBUG, "SSL: Failed - tls_out available to "
			   "report error");
		return -1;
	}

	return 0;
}
Beispiel #6
0
struct fst_session * fst_session_create(struct fst_group *g)
{
	struct fst_session *s;
	u32 id;

	WPA_ASSERT(!is_zero_ether_addr(own_addr));

	id = fst_find_free_session_id();
	if (id == FST_INVALID_SESSION_ID) {
		fst_printf(MSG_ERROR, "Cannot assign new session ID");
		return NULL;
	}

	s = os_zalloc(sizeof(*s));
	if (!s) {
		fst_printf(MSG_ERROR, "Cannot allocate new session object");
		return NULL;
	}

	s->id = id;
	s->group = g;
	s->state = FST_SESSION_STATE_INITIAL;

	s->data.llt_ms = FST_LLT_MS_DEFAULT;

	fst_printf(MSG_INFO, "Session %u created", s->id);

	dl_list_add_tail(&global_sessions_list, &s->global_sessions_lentry);

	foreach_fst_ctrl_call(on_session_added, s);

	return s;
}
static int wpa_gen_wpa_ie_osen(u8 *wpa_ie, size_t wpa_ie_len,
			       int pairwise_cipher, int group_cipher,
			       int key_mgmt)
{
	u8 *pos, *len;
	u32 suite;

	if (wpa_ie_len < 2 + 4 + RSN_SELECTOR_LEN +
	    2 + RSN_SELECTOR_LEN + 2 + RSN_SELECTOR_LEN)
		return -1;

	pos = wpa_ie;
	*pos++ = WLAN_EID_VENDOR_SPECIFIC;
	len = pos++; /* to be filled */
	WPA_PUT_BE24(pos, OUI_WFA);
	pos += 3;
	*pos++ = HS20_OSEN_OUI_TYPE;

	/* Group Data Cipher Suite */
	suite = wpa_cipher_to_suite(WPA_PROTO_RSN, group_cipher);
	if (suite == 0) {
		wpa_printf(MSG_WARNING, "Invalid group cipher (%d).",
			   group_cipher);
		return -1;
	}
	RSN_SELECTOR_PUT(pos, suite);
	pos += RSN_SELECTOR_LEN;

	/* Pairwise Cipher Suite Count and List */
	WPA_PUT_LE16(pos, 1);
	pos += 2;
	suite = wpa_cipher_to_suite(WPA_PROTO_RSN, pairwise_cipher);
	if (suite == 0 ||
	    (!wpa_cipher_valid_pairwise(pairwise_cipher) &&
	     pairwise_cipher != WPA_CIPHER_NONE)) {
		wpa_printf(MSG_WARNING, "Invalid pairwise cipher (%d).",
			   pairwise_cipher);
		return -1;
	}
	RSN_SELECTOR_PUT(pos, suite);
	pos += RSN_SELECTOR_LEN;

	/* AKM Suite Count and List */
	WPA_PUT_LE16(pos, 1);
	pos += 2;
	RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_OSEN);
	pos += RSN_SELECTOR_LEN;

	*len = pos - len - 1;

	WPA_ASSERT((size_t) (pos - wpa_ie) <= wpa_ie_len);

	return pos - wpa_ie;
}
Beispiel #8
0
int fst_session_initiate_switch(struct fst_session *s)
{
	struct fst_ack_req req;
	int res;
	u8 dialog_token;

	if (!fst_session_is_ready(s)) {
		fst_printf_session(s, MSG_ERROR,
				   "cannot initiate switch due to wrong setup state (%d)",
				   s->state);
		return -1;
	}

	dialog_token = fst_group_assign_dialog_token(s->group);

	WPA_ASSERT(s->data.new_iface != NULL);
	WPA_ASSERT(s->data.old_iface != NULL);

	fst_printf_session(s, MSG_INFO, "initiating FST switch: %s => %s",
			   fst_iface_get_name(s->data.old_iface),
			   fst_iface_get_name(s->data.new_iface));

	os_memset(&req, 0, sizeof(req));

	req.action = FST_ACTION_ACK_REQUEST;
	req.dialog_token = dialog_token;
	req.fsts_id = host_to_le32(s->data.fsts_id);

	res = fst_session_send_action(s, FALSE, &req, sizeof(req), NULL);
	if (!res) {
		fst_printf_sframe(s, FALSE, MSG_INFO, "FST Ack Request sent");
		fst_session_set_state(s, FST_SESSION_STATE_TRANSITION_DONE,
				      NULL);
		fst_session_stt_arm(s);
	} else {
		fst_printf_sframe(s, FALSE, MSG_ERROR,
				  "Cannot send FST Ack Request");
	}

	return res;
}
Beispiel #9
0
static void
fst_session_handle_ack_response(struct fst_session *s,
				struct fst_iface *iface,
				const struct ieee80211_mgmt *mgmt,
				size_t frame_len)
{
	const struct fst_ack_res *res;
	size_t plen = frame_len - IEEE80211_HDRLEN - 1;
	union fst_session_state_switch_extra evext = {
		.to_initial = {
			.reason = REASON_SWITCH,
			.initiator = FST_INITIATOR_LOCAL,
		},
	};

	if (!fst_session_is_switch_requested(s)) {
		fst_printf_siface(s, iface, MSG_ERROR,
				  "Ack Response in inappropriate session state (%s)",
				  fst_session_state_name(s->state));
		return;
	}

	WPA_ASSERT(s->data.new_iface != NULL);

	if (iface != s->data.new_iface) {
		fst_printf_siface(s, iface, MSG_ERROR,
				  "Ack response received on wrong interface");
		return;
	}

	if (plen < sizeof(*res)) {
		fst_printf_session(s, MSG_WARNING,
				   "Too short FST Ack Response dropped");
		return;
	}
	res = (const struct fst_ack_res *)
		(((const u8 *) mgmt) + IEEE80211_HDRLEN + 1);

	if (le_to_host32(res->fsts_id) != s->data.fsts_id) {
		fst_printf_siface(s, iface, MSG_ERROR,
				  "Ack response for wrong FST Setup ID (%u)",
				  le_to_host32(res->fsts_id));
		return;
	}

	fst_session_set_state(s, FST_SESSION_STATE_TRANSITION_CONFIRMED, NULL);
	fst_session_set_state(s, FST_SESSION_STATE_INITIAL, &evext);

	fst_session_stt_disarm(s);
}
Beispiel #10
0
enum mb_band_id fst_hw_mode_to_band(enum hostapd_hw_mode mode)
{
	switch (mode) {
	case HOSTAPD_MODE_IEEE80211B:
	case HOSTAPD_MODE_IEEE80211G:
		return MB_BAND_ID_WIFI_2_4GHZ;
	case HOSTAPD_MODE_IEEE80211A:
		return MB_BAND_ID_WIFI_5GHZ;
	case HOSTAPD_MODE_IEEE80211AD:
		return MB_BAND_ID_WIFI_60GHZ;
	default:
		WPA_ASSERT(0);
		return MB_BAND_ID_WIFI_2_4GHZ;
	}
}
static int eap_tls_process_input(struct eap_sm *sm, struct eap_ssl_data *data,
				 const u8 *in_data, size_t in_len,
				 u8 **out_data, size_t *out_len)
{
	const u8 *msg;
	size_t msg_len;
	int need_more_input;
	u8 *appl_data;
	size_t appl_data_len;

	msg = eap_tls_data_reassemble(sm, data, in_data, in_len,
				      &msg_len, &need_more_input);
	if (msg == NULL)
		return need_more_input ? 1 : -1;

	/* Full TLS message reassembled - continue handshake processing */
	if (data->tls_out) {
		/* This should not happen.. */
		wpa_printf(MSG_INFO, "SSL: eap_tls_process_helper - pending "
			   "tls_out data even though tls_out_len = 0");
		os_free(data->tls_out);
		WPA_ASSERT(data->tls_out == NULL);
	}
	appl_data = NULL;
	data->tls_out = tls_connection_handshake(sm->ssl_ctx, data->conn,
						 msg, msg_len,
						 &data->tls_out_len,
						 &appl_data, &appl_data_len);

	/* Clear reassembled input data (if the buffer was needed). */
	data->tls_in_left = data->tls_in_total = data->tls_in_len = 0;
	os_free(data->tls_in);
	data->tls_in = NULL;

	if (appl_data &&
	    tls_connection_established(sm->ssl_ctx, data->conn) &&
	    !tls_connection_get_failed(sm->ssl_ctx, data->conn)) {
		wpa_hexdump_key(MSG_MSGDUMP, "SSL: Application data",
				appl_data, appl_data_len);
		*out_data = appl_data;
		*out_len = appl_data_len;
		return 2;
	}

	os_free(appl_data);

	return 0;
}
/**
 * eap_tls_process_input - Process incoming TLS message
 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
 * @data: Data for TLS processing
 * @in_data: Message received from the server
 * @in_len: Length of in_data
 * @out_data: Buffer for returning a pointer to application data (if available)
 * Returns: 0 on success, 1 if more input data is needed, 2 if application data
 * is available, -1 on failure
 */
static int eap_tls_process_input(struct eap_sm *sm, struct eap_ssl_data *data,
				 const u8 *in_data, size_t in_len,
				 struct wpabuf **out_data)
{
	const u8 *msg;
	size_t msg_len;
	int need_more_input;
	u8 *appl_data;
	size_t appl_data_len;

	msg = eap_peer_tls_data_reassemble(data, in_data, in_len,
					   &msg_len, &need_more_input);
	if (msg == NULL)
		return need_more_input ? 1 : -1;

	/* Full TLS message reassembled - continue handshake processing */
	if (data->tls_out) {
		/* This should not happen.. */
		wpa_printf(MSG_INFO, "SSL: eap_tls_process_input - pending "
			   "tls_out data even though tls_out_len = 0");
		os_free(data->tls_out);
		WPA_ASSERT(data->tls_out == NULL);
	}
	appl_data = NULL;
	data->tls_out = tls_connection_handshake(sm->ssl_ctx, data->conn,
						 msg, msg_len,
						 &data->tls_out_len,
						 &appl_data, &appl_data_len);

	eap_peer_tls_reset_input(data);

	if (appl_data &&
	    tls_connection_established(sm->ssl_ctx, data->conn) &&
	    !tls_connection_get_failed(sm->ssl_ctx, data->conn)) {
		wpa_hexdump_key(MSG_MSGDUMP, "SSL: Application data",
				appl_data, appl_data_len);
		*out_data = wpabuf_alloc_ext_data(appl_data, appl_data_len);
		if (*out_data == NULL) {
			os_free(appl_data);
			return -1;
		}
		return 2;
	}

	os_free(appl_data);

	return 0;
}
int eap_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data,
			   EapType eap_type, int peap_version,
			   u8 id, const u8 *in_data, size_t in_len,
			   u8 **out_data, size_t *out_len)
{
	int ret = 0;

	WPA_ASSERT(data->tls_out_len == 0 || in_len == 0);
	*out_len = 0;
	*out_data = NULL;

	if (data->tls_out_len == 0) {
		/* No more data to send out - expect to receive more data from
		 * the AS. */
		int res = eap_tls_process_input(sm, data, in_data, in_len,
						out_data, out_len);
		if (res)
			return res;
	}

	if (data->tls_out == NULL) {
		data->tls_out_len = 0;
		return -1;
	}

	if (tls_connection_get_failed(sm->ssl_ctx, data->conn)) {
		wpa_printf(MSG_DEBUG, "SSL: Failed - tls_out available to "
			   "report error");
		ret = -1;
		/* TODO: clean pin if engine used? */
	}

	if (data->tls_out_len == 0) {
		/* TLS negotiation should now be complete since all other cases
		 * needing more data should have been caught above based on
		 * the TLS Message Length field. */
		wpa_printf(MSG_DEBUG, "SSL: No data to be sent out");
		os_free(data->tls_out);
		data->tls_out = NULL;
		return 1;
	}

	return eap_tls_process_output(data, eap_type, peap_version, id, ret,
				      out_data, out_len);
}
Beispiel #14
0
int eap_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data,
			   u8 *in_data, size_t in_len)
{
	WPA_ASSERT(data->tls_out_len == 0 || in_len == 0);

	if (data->tls_out_len == 0) {
		/* No more data to send out - expect to receive more data from
		 * the peer. */
		int res = eap_tls_data_reassemble(sm, data, &in_data, &in_len);
		if (res < 0 || res == 1) {
			wpa_printf(MSG_DEBUG, "SSL: data reassembly failed");
			return res;
		}
		/* Full TLS message reassembled - continue handshake processing
		 */
		if (data->tls_out) {
			/* This should not happen.. */
			wpa_printf(MSG_INFO, "SSL: eap_tls_process_helper - "
				   "pending tls_out data even though "
				   "tls_out_len = 0");
			free(data->tls_out);
			WPA_ASSERT(data->tls_out == NULL);
		}
		data->tls_out = tls_connection_server_handshake(
			sm->ssl_ctx, data->conn, in_data, in_len,
			&data->tls_out_len);

		/* Clear reassembled input data (if the buffer was needed). */
		data->tls_in_left = data->tls_in_total = data->tls_in_len = 0;
		free(data->tls_in);
		data->tls_in = NULL;
	}

	if (data->tls_out == NULL) {
		wpa_printf(MSG_DEBUG, "SSL: failed to generate output data");
		data->tls_out_len = 0;
		return -1;
	}
	if (data->tls_out_len == 0) {
		/* TLS negotiation should now be complete since all other cases
		 * needing more that should have been catched above based on
		 * the TLS Message Length field. */
		wpa_printf(MSG_DEBUG, "SSL: No data to be sent out");
		free(data->tls_out);
		data->tls_out = NULL;

		if (tls_connection_get_read_alerts(sm->ssl_ctx, data->conn)) {
			wpa_printf(MSG_DEBUG, "SSL: Remote end sent a fatal "
				   "alert - abort handshake");
			return -1;
		}

		return 1;
	}

	wpa_printf(MSG_DEBUG, "SSL: %lu bytes left to be sent out (of total "
		   "%lu bytes)",
		   (unsigned long) data->tls_out_len - data->tls_out_pos,
		   (unsigned long) data->tls_out_len);

	return 0;
}
Beispiel #15
0
void fst_session_global_deinit(void)
{
	WPA_ASSERT(dl_list_empty(&global_sessions_list));
}
int eap_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data,
			   int eap_type, int peap_version,
			   u8 id, const u8 *in_data, size_t in_len,
			   u8 **out_data, size_t *out_len)
{
	size_t len;
	u8 *pos, *flags;
	struct eap_hdr *resp;
	int ret = 0;

	WPA_ASSERT(data->tls_out_len == 0 || in_len == 0);
	*out_len = 0;

	if (data->tls_out_len == 0) {
		/* No more data to send out - expect to receive more data from
		 * the AS. */
		const u8 *msg;
		size_t msg_len;
		int need_more_input;

		msg = eap_tls_data_reassemble(sm, data, in_data, in_len,
					      &msg_len, &need_more_input);
		if (msg == NULL)
			return need_more_input ? 1 : -1;

		/* Full TLS message reassembled - continue handshake processing
		 */
		if (data->tls_out) {
			/* This should not happen.. */
			wpa_printf(MSG_INFO, "SSL: eap_tls_process_helper - "
				   "pending tls_out data even though "
				   "tls_out_len = 0");
			free(data->tls_out);
			WPA_ASSERT(data->tls_out == NULL);
		}
		data->tls_out = tls_connection_handshake(sm->ssl_ctx,
							 data->conn,
							 msg, msg_len,
							 &data->tls_out_len);

		/* Clear reassembled input data (if the buffer was needed). */
		data->tls_in_left = data->tls_in_total = data->tls_in_len = 0;
		free(data->tls_in);
		data->tls_in = NULL;
	}

	if (data->tls_out == NULL) {
		data->tls_out_len = 0;
		return -1;
	}
	if (tls_connection_get_failed(sm->ssl_ctx, data->conn)) {
		wpa_printf(MSG_DEBUG, "SSL: Failed - tls_out available to "
			   "report error");
		ret = -1;
		/* TODO: clean pin if engine used? */
	}

	if (data->tls_out_len == 0) {
		/* TLS negotiation should now be complete since all other cases
		 * needing more that should have been catched above based on
		 * the TLS Message Length field. */
		wpa_printf(MSG_DEBUG, "SSL: No data to be sent out");
		free(data->tls_out);
		data->tls_out = NULL;
		return 1;
	}

	wpa_printf(MSG_DEBUG, "SSL: %lu bytes left to be sent out (of total "
		   "%lu bytes)",
		   (unsigned long) data->tls_out_len - data->tls_out_pos,
		   (unsigned long) data->tls_out_len);
	resp = malloc(sizeof(struct eap_hdr) + 2 + 4 + data->tls_out_limit);
	if (resp == NULL) {
		*out_data = NULL;
		return -1;
	}
	resp->code = EAP_CODE_RESPONSE;
	resp->identifier = id;
	pos = (u8 *) (resp + 1);
	*pos++ = eap_type;
	flags = pos++;
	*flags = peap_version;
	if (data->tls_out_pos == 0 &&
	    (data->tls_out_len > data->tls_out_limit ||
	     data->include_tls_length)) {
		*flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED;
		*pos++ = (data->tls_out_len >> 24) & 0xff;
		*pos++ = (data->tls_out_len >> 16) & 0xff;
		*pos++ = (data->tls_out_len >> 8) & 0xff;
		*pos++ = data->tls_out_len & 0xff;
	}
Beispiel #17
0
static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len,
			      int pairwise_cipher, int group_cipher,
			      int key_mgmt, int mgmt_group_cipher,
			      struct wpa_sm *sm)
{
#ifndef CONFIG_NO_WPA2
	u8 *pos;
	struct rsn_ie_hdr *hdr;
	u16 capab;

	if (rsn_ie_len < sizeof(*hdr) + RSN_SELECTOR_LEN +
	    2 + RSN_SELECTOR_LEN + 2 + RSN_SELECTOR_LEN + 2 +
	    (sm->cur_pmksa ? 2 + PMKID_LEN : 0))
		return -1;

	hdr = (struct rsn_ie_hdr *) rsn_ie;
	hdr->elem_id = RSN_INFO_ELEM;
	WPA_PUT_LE16(hdr->version, RSN_VERSION);
	pos = (u8 *) (hdr + 1);

	if (group_cipher == WPA_CIPHER_CCMP) {
		os_memcpy(pos, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN);
	} else if (group_cipher == WPA_CIPHER_TKIP) {
		os_memcpy(pos, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN);
	} else if (group_cipher == WPA_CIPHER_WEP104) {
		os_memcpy(pos, RSN_CIPHER_SUITE_WEP104, RSN_SELECTOR_LEN);
	} else if (group_cipher == WPA_CIPHER_WEP40) {
		os_memcpy(pos, RSN_CIPHER_SUITE_WEP40, RSN_SELECTOR_LEN);
	} else {
		wpa_printf(MSG_WARNING, "Invalid group cipher (%d).",
			   group_cipher);
		return -1;
	}
	pos += RSN_SELECTOR_LEN;

	*pos++ = 1;
	*pos++ = 0;
	if (pairwise_cipher == WPA_CIPHER_CCMP) {
		os_memcpy(pos, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN);
	} else if (pairwise_cipher == WPA_CIPHER_TKIP) {
		os_memcpy(pos, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN);
	} else if (pairwise_cipher == WPA_CIPHER_NONE) {
		os_memcpy(pos, RSN_CIPHER_SUITE_NONE, RSN_SELECTOR_LEN);
	} else {
		wpa_printf(MSG_WARNING, "Invalid pairwise cipher (%d).",
			   pairwise_cipher);
		return -1;
	}
	pos += RSN_SELECTOR_LEN;

	*pos++ = 1;
	*pos++ = 0;
	if (key_mgmt == WPA_KEY_MGMT_IEEE8021X) {
		os_memcpy(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X,
			  RSN_SELECTOR_LEN);
	} else if (key_mgmt == WPA_KEY_MGMT_PSK) {
		os_memcpy(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X,
			  RSN_SELECTOR_LEN);
	} else {
		wpa_printf(MSG_WARNING, "Invalid key management type (%d).",
			   key_mgmt);
		return -1;
	}
	pos += RSN_SELECTOR_LEN;

	/* RSN Capabilities */
	capab = 0;
#ifdef CONFIG_IEEE80211W
	if (mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC)
		capab |= WPA_CAPABILITY_MGMT_FRAME_PROTECTION;
#endif /* CONFIG_IEEE80211W */
	WPA_PUT_LE16(pos, capab);
	pos += 2;

	if (sm->cur_pmksa) {
		/* PMKID Count (2 octets, little endian) */
		*pos++ = 1;
		*pos++ = 0;
		/* PMKID */
		os_memcpy(pos, sm->cur_pmksa->pmkid, PMKID_LEN);
		pos += PMKID_LEN;
	}

#ifdef CONFIG_IEEE80211W
	if (mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) {
		if (!sm->cur_pmksa) {
			/* PMKID Count */
			WPA_PUT_LE16(pos, 0);
			pos += 2;

			/* Management Group Cipher Suite */
			memcpy(pos, RSN_CIPHER_SUITE_AES_128_CMAC,
			       RSN_SELECTOR_LEN);
			pos += RSN_SELECTOR_LEN;
		}
	}
#endif /* CONFIG_IEEE80211W */

	hdr->len = (pos - rsn_ie) - 2;

	WPA_ASSERT((size_t) (pos - rsn_ie) <= rsn_ie_len);

	return pos - rsn_ie;
#else /* CONFIG_NO_WPA2 */
	return -1;
#endif /* CONFIG_NO_WPA2 */
}
static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len,
			      int pairwise_cipher, int group_cipher,
			      int key_mgmt, int mgmt_group_cipher,
			      struct wpa_sm *sm)
{
#ifndef CONFIG_NO_WPA2
	u8 *pos;
	struct rsn_ie_hdr *hdr;
	u16 capab;
	u32 suite;

	if (rsn_ie_len < sizeof(*hdr) + RSN_SELECTOR_LEN +
	    2 + RSN_SELECTOR_LEN + 2 + RSN_SELECTOR_LEN + 2 +
	    (sm->cur_pmksa ? 2 + PMKID_LEN : 0)) {
		wpa_printf(MSG_DEBUG, "RSN: Too short IE buffer (%lu bytes)",
			   (unsigned long) rsn_ie_len);
		return -1;
	}

	hdr = (struct rsn_ie_hdr *) rsn_ie;
	hdr->elem_id = WLAN_EID_RSN;
	WPA_PUT_LE16(hdr->version, RSN_VERSION);
	pos = (u8 *) (hdr + 1);

	suite = wpa_cipher_to_suite(WPA_PROTO_RSN, group_cipher);
	if (suite == 0) {
		wpa_printf(MSG_WARNING, "Invalid group cipher (%d).",
			   group_cipher);
		return -1;
	}
	RSN_SELECTOR_PUT(pos, suite);
	pos += RSN_SELECTOR_LEN;

	*pos++ = 1;
	*pos++ = 0;
	suite = wpa_cipher_to_suite(WPA_PROTO_RSN, pairwise_cipher);
	if (suite == 0 ||
	    (!wpa_cipher_valid_pairwise(pairwise_cipher) &&
	     pairwise_cipher != WPA_CIPHER_NONE)) {
		wpa_printf(MSG_WARNING, "Invalid pairwise cipher (%d).",
			   pairwise_cipher);
		return -1;
	}
	RSN_SELECTOR_PUT(pos, suite);
	pos += RSN_SELECTOR_LEN;

	*pos++ = 1;
	*pos++ = 0;
	if (key_mgmt == WPA_KEY_MGMT_IEEE8021X) {
		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X);
	} else if (key_mgmt == WPA_KEY_MGMT_PSK) {
		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X);
	} else if (key_mgmt == WPA_KEY_MGMT_CCKM) {
		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_CCKM);
#ifdef CONFIG_IEEE80211R
	} else if (key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X) {
		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X);
	} else if (key_mgmt == WPA_KEY_MGMT_FT_PSK) {
		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK);
#endif /* CONFIG_IEEE80211R */
#ifdef CONFIG_IEEE80211W
	} else if (key_mgmt == WPA_KEY_MGMT_IEEE8021X_SHA256) {
		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA256);
	} else if (key_mgmt == WPA_KEY_MGMT_PSK_SHA256) {
		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_SHA256);
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_SAE
	} else if (key_mgmt == WPA_KEY_MGMT_SAE) {
		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE);
	} else if (key_mgmt == WPA_KEY_MGMT_FT_SAE) {
		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE);
#endif /* CONFIG_SAE */
	} else {
		wpa_printf(MSG_WARNING, "Invalid key management type (%d).",
			   key_mgmt);
		return -1;
	}
	pos += RSN_SELECTOR_LEN;

	/* RSN Capabilities */
	capab = 0;
#ifdef CONFIG_IEEE80211W
	if (sm->mfp)
		capab |= WPA_CAPABILITY_MFPC;
	if (sm->mfp == 2)
		capab |= WPA_CAPABILITY_MFPR;
#endif /* CONFIG_IEEE80211W */
	WPA_PUT_LE16(pos, capab);
	pos += 2;

	if (sm->cur_pmksa) {
		/* PMKID Count (2 octets, little endian) */
		*pos++ = 1;
		*pos++ = 0;
		/* PMKID */
		os_memcpy(pos, sm->cur_pmksa->pmkid, PMKID_LEN);
		pos += PMKID_LEN;
	}

#ifdef CONFIG_IEEE80211W
	if (mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) {
		if (!sm->cur_pmksa) {
			/* PMKID Count */
			WPA_PUT_LE16(pos, 0);
			pos += 2;
		}

		/* Management Group Cipher Suite */
		RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
		pos += RSN_SELECTOR_LEN;
	}
#endif /* CONFIG_IEEE80211W */

	hdr->len = (pos - rsn_ie) - 2;

	WPA_ASSERT((size_t) (pos - rsn_ie) <= rsn_ie_len);

	return pos - rsn_ie;
#else /* CONFIG_NO_WPA2 */
	return -1;
#endif /* CONFIG_NO_WPA2 */
}
Beispiel #19
0
static void fst_session_handle_ack_request(struct fst_session *s,
					   struct fst_iface *iface,
					   const struct ieee80211_mgmt *mgmt,
					   size_t frame_len)
{
	const struct fst_ack_req *req;
	size_t plen = frame_len - IEEE80211_HDRLEN - 1;
	struct fst_ack_res res;
	union fst_session_state_switch_extra evext = {
		.to_initial = {
			.reason = REASON_SWITCH,
			.initiator = FST_INITIATOR_REMOTE,
		},
	};

	if (!fst_session_is_ready(s) && !fst_session_is_switch_requested(s)) {
		fst_printf_siface(s, iface, MSG_ERROR,
				  "cannot initiate switch due to wrong session state (%s)",
				  fst_session_state_name(s->state));
		return;
	}

	WPA_ASSERT(s->data.new_iface != NULL);

	if (iface != s->data.new_iface) {
		fst_printf_siface(s, iface, MSG_ERROR,
				  "Ack received on wrong interface");
		return;
	}

	if (plen < sizeof(*req)) {
		fst_printf_session(s, MSG_WARNING,
				   "Too short FST Ack Request dropped");
		return;
	}
	req = (const struct fst_ack_req *)
		(((const u8 *) mgmt) + IEEE80211_HDRLEN + 1);

	if (le_to_host32(req->fsts_id) != s->data.fsts_id) {
		fst_printf_siface(s, iface, MSG_WARNING,
				  "Ack for wrong FST Setup ID (%u)",
				  le_to_host32(req->fsts_id));
		return;
	}

	os_memset(&res, 0, sizeof(res));

	res.action = FST_ACTION_ACK_RESPONSE;
	res.dialog_token = req->dialog_token;
	res.fsts_id = req->fsts_id;

	if (!fst_session_send_action(s, FALSE, &res, sizeof(res), NULL)) {
		fst_printf_sframe(s, FALSE, MSG_INFO, "FST Ack Response sent");
		fst_session_stt_disarm(s);
		fst_session_set_state(s, FST_SESSION_STATE_TRANSITION_DONE,
				      NULL);
		fst_session_set_state(s, FST_SESSION_STATE_TRANSITION_CONFIRMED,
				      NULL);
		fst_session_set_state(s, FST_SESSION_STATE_INITIAL, &evext);
	}
}
static int wpa_gen_wpa_ie_wpa(u8 *wpa_ie, size_t wpa_ie_len,
			      int pairwise_cipher, int group_cipher,
			      int key_mgmt)
{
	u8 *pos;
	struct wpa_ie_hdr *hdr;
	u32 suite;

	if (wpa_ie_len < sizeof(*hdr) + WPA_SELECTOR_LEN +
	    2 + WPA_SELECTOR_LEN + 2 + WPA_SELECTOR_LEN)
		return -1;

	hdr = (struct wpa_ie_hdr *) wpa_ie;
	hdr->elem_id = WLAN_EID_VENDOR_SPECIFIC;
	RSN_SELECTOR_PUT(hdr->oui, WPA_OUI_TYPE);
	WPA_PUT_LE16(hdr->version, WPA_VERSION);
	pos = (u8 *) (hdr + 1);

	suite = wpa_cipher_to_suite(WPA_PROTO_WPA, group_cipher);
	if (suite == 0) {
		wpa_printf(MSG_WARNING, "Invalid group cipher (%d).",
			   group_cipher);
		return -1;
	}
	RSN_SELECTOR_PUT(pos, suite);
	pos += WPA_SELECTOR_LEN;

	*pos++ = 1;
	*pos++ = 0;
	suite = wpa_cipher_to_suite(WPA_PROTO_WPA, pairwise_cipher);
	if (suite == 0 ||
	    (!wpa_cipher_valid_pairwise(pairwise_cipher) &&
	     pairwise_cipher != WPA_CIPHER_NONE)) {
		wpa_printf(MSG_WARNING, "Invalid pairwise cipher (%d).",
			   pairwise_cipher);
		return -1;
	}
	RSN_SELECTOR_PUT(pos, suite);
	pos += WPA_SELECTOR_LEN;

	*pos++ = 1;
	*pos++ = 0;
	if (key_mgmt == WPA_KEY_MGMT_IEEE8021X) {
		RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X);
	} else if (key_mgmt == WPA_KEY_MGMT_PSK) {
		RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X);
	} else if (key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
		RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_NONE);
	} else if (key_mgmt == WPA_KEY_MGMT_CCKM) {
		RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_CCKM);
	} else {
		wpa_printf(MSG_WARNING, "Invalid key management type (%d).",
			   key_mgmt);
		return -1;
	}
	pos += WPA_SELECTOR_LEN;

	/* WPA Capabilities; use defaults, so no need to include it */

	hdr->len = (pos - wpa_ie) - 2;

	WPA_ASSERT((size_t) (pos - wpa_ie) <= wpa_ie_len);

	return pos - wpa_ie;
}
Beispiel #21
0
static int wpa_gen_wpa_ie_wpa(u8 *wpa_ie, size_t wpa_ie_len,
			      int pairwise_cipher, int group_cipher,
			      int key_mgmt)
{
	u8 *pos;
	struct wpa_ie_hdr *hdr;

	if (wpa_ie_len < sizeof(*hdr) + WPA_SELECTOR_LEN +
	    2 + WPA_SELECTOR_LEN + 2 + WPA_SELECTOR_LEN)
		return -1;

	hdr = (struct wpa_ie_hdr *) wpa_ie;
	hdr->elem_id = GENERIC_INFO_ELEM;
	os_memcpy(hdr->oui, WPA_OUI_TYPE, WPA_SELECTOR_LEN);
	WPA_PUT_LE16(hdr->version, WPA_VERSION);
	pos = (u8 *) (hdr + 1);

	if (group_cipher == WPA_CIPHER_CCMP) {
		os_memcpy(pos, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN);
	} else if (group_cipher == WPA_CIPHER_TKIP) {
		os_memcpy(pos, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN);
	} else if (group_cipher == WPA_CIPHER_WEP104) {
		os_memcpy(pos, WPA_CIPHER_SUITE_WEP104, WPA_SELECTOR_LEN);
	} else if (group_cipher == WPA_CIPHER_WEP40) {
		os_memcpy(pos, WPA_CIPHER_SUITE_WEP40, WPA_SELECTOR_LEN);
	} else {
		wpa_printf(MSG_WARNING, "Invalid group cipher (%d).",
			   group_cipher);
		return -1;
	}
	pos += WPA_SELECTOR_LEN;

	*pos++ = 1;
	*pos++ = 0;
	if (pairwise_cipher == WPA_CIPHER_CCMP) {
		os_memcpy(pos, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN);
	} else if (pairwise_cipher == WPA_CIPHER_TKIP) {
		os_memcpy(pos, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN);
	} else if (pairwise_cipher == WPA_CIPHER_NONE) {
		os_memcpy(pos, WPA_CIPHER_SUITE_NONE, WPA_SELECTOR_LEN);
	} else {
		wpa_printf(MSG_WARNING, "Invalid pairwise cipher (%d).",
			   pairwise_cipher);
		return -1;
	}
	pos += WPA_SELECTOR_LEN;

	*pos++ = 1;
	*pos++ = 0;
	if (key_mgmt == WPA_KEY_MGMT_IEEE8021X) {
		os_memcpy(pos, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X,
			  WPA_SELECTOR_LEN);
	} else if (key_mgmt == WPA_KEY_MGMT_PSK) {
		os_memcpy(pos, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X,
			  WPA_SELECTOR_LEN);
	} else if (key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
		os_memcpy(pos, WPA_AUTH_KEY_MGMT_NONE, WPA_SELECTOR_LEN);
	} else {
		wpa_printf(MSG_WARNING, "Invalid key management type (%d).",
			   key_mgmt);
		return -1;
	}
	pos += WPA_SELECTOR_LEN;

	/* WPA Capabilities; use defaults, so no need to include it */

	hdr->len = (pos - wpa_ie) - 2;

	WPA_ASSERT((size_t) (pos - wpa_ie) <= wpa_ie_len);

	return pos - wpa_ie;
}