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; }
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; }
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; }
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; }
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; }
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; }
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); }
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); }
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; }
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; }
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 */ }
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; }
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; }