int hostapd_wps_nfc_token_enable(struct hostapd_data *hapd) { struct wps_context *wps = hapd->wps; if (wps == NULL) return -1; if (!hapd->conf->wps_nfc_dh_pubkey || !hapd->conf->wps_nfc_dh_privkey || !hapd->conf->wps_nfc_dev_pw || !hapd->conf->wps_nfc_dev_pw_id) return -1; hostapd_wps_nfc_clear(wps); wps->ap_nfc_dev_pw_id = hapd->conf->wps_nfc_dev_pw_id; wps->ap_nfc_dh_pubkey = wpabuf_dup(hapd->conf->wps_nfc_dh_pubkey); wps->ap_nfc_dh_privkey = wpabuf_dup(hapd->conf->wps_nfc_dh_privkey); wps->ap_nfc_dev_pw = wpabuf_dup(hapd->conf->wps_nfc_dev_pw); if (!wps->ap_nfc_dh_pubkey || !wps->ap_nfc_dh_privkey || !wps->ap_nfc_dev_pw) { hostapd_wps_nfc_clear(wps); return -1; } return 0; }
/** * eap_server_sm_init - Allocate and initialize EAP server state machine * @eapol_ctx: Context data to be used with eapol_cb calls * @eapol_cb: Pointer to EAPOL callback functions * @conf: EAP configuration * Returns: Pointer to the allocated EAP state machine or %NULL on failure * * This function allocates and initializes an EAP state machine. */ struct eap_sm * eap_server_sm_init(void *eapol_ctx, struct eapol_callbacks *eapol_cb, struct eap_config *conf) { struct eap_sm *sm; sm = os_zalloc(sizeof(*sm)); if (sm == NULL) return NULL; sm->eapol_ctx = eapol_ctx; sm->eapol_cb = eapol_cb; sm->MaxRetrans = 5; /* RFC 3748: max 3-5 retransmissions suggested */ sm->ssl_ctx = conf->ssl_ctx; sm->msg_ctx = conf->msg_ctx; sm->eap_sim_db_priv = conf->eap_sim_db_priv; sm->backend_auth = conf->backend_auth; sm->eap_server = conf->eap_server; if (conf->pac_opaque_encr_key) { sm->pac_opaque_encr_key = os_malloc(16); if (sm->pac_opaque_encr_key) { os_memcpy(sm->pac_opaque_encr_key, conf->pac_opaque_encr_key, 16); } } if (conf->eap_fast_a_id) { sm->eap_fast_a_id = os_malloc(conf->eap_fast_a_id_len); if (sm->eap_fast_a_id) { os_memcpy(sm->eap_fast_a_id, conf->eap_fast_a_id, conf->eap_fast_a_id_len); sm->eap_fast_a_id_len = conf->eap_fast_a_id_len; } } if (conf->eap_fast_a_id_info) sm->eap_fast_a_id_info = os_strdup(conf->eap_fast_a_id_info); sm->eap_fast_prov = conf->eap_fast_prov; sm->pac_key_lifetime = conf->pac_key_lifetime; sm->pac_key_refresh_time = conf->pac_key_refresh_time; sm->eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind; sm->tnc = conf->tnc; sm->wps = conf->wps; if (conf->assoc_wps_ie) sm->assoc_wps_ie = wpabuf_dup(conf->assoc_wps_ie); if (conf->assoc_p2p_ie) sm->assoc_p2p_ie = wpabuf_dup(conf->assoc_p2p_ie); if (conf->peer_addr) os_memcpy(sm->peer_addr, conf->peer_addr, ETH_ALEN); sm->fragment_size = conf->fragment_size; sm->pwd_group = conf->pwd_group; sm->pbc_in_m1 = conf->pbc_in_m1; sm->server_id = conf->server_id; sm->server_id_len = conf->server_id_len; #ifdef CONFIG_TESTING_OPTIONS sm->tls_test_flags = conf->tls_test_flags; #endif /* CONFIG_TESTING_OPTIONS */ wpa_printf(MSG_DEBUG, "EAP: Server state machine created"); return sm; }
int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg) { struct wpabuf *pubkey; wpa_printf(MSG_DEBUG, "WPS: * Public Key"); wpabuf_free(wps->dh_privkey); if (wps->dev_pw_id != DEV_PW_DEFAULT && wps->wps->dh_privkey) { wpa_printf(MSG_DEBUG, "WPS: Using pre-configured DH keys"); wps->dh_privkey = wpabuf_dup(wps->wps->dh_privkey); wps->dh_ctx = wps->wps->dh_ctx; wps->wps->dh_ctx = NULL; pubkey = wpabuf_dup(wps->wps->dh_pubkey); #ifdef CONFIG_WPS_NFC } else if (wps->dev_pw_id >= 0x10 && wps->wps->ap && wps->dev_pw_id == wps->wps->ap_nfc_dev_pw_id) { wpa_printf(MSG_DEBUG, "WPS: Using NFC password token DH keys"); wps->dh_privkey = wpabuf_dup(wps->wps->ap_nfc_dh_privkey); pubkey = wpabuf_dup(wps->wps->ap_nfc_dh_pubkey); wps->dh_ctx = dh5_init_fixed(wps->dh_privkey, pubkey); #endif /* CONFIG_WPS_NFC */ } else { wpa_printf(MSG_DEBUG, "WPS: Generate new DH keys"); wps->dh_privkey = NULL; dh5_free(wps->dh_ctx); wps->dh_ctx = dh5_init(&wps->dh_privkey, &pubkey); pubkey = wpabuf_zeropad(pubkey, 192); } if (wps->dh_ctx == NULL || wps->dh_privkey == NULL || pubkey == NULL) { wpa_printf(MSG_DEBUG, "WPS: Failed to initialize " "Diffie-Hellman handshake"); wpabuf_free(pubkey); return -1; } wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH Private Key", wps->dh_privkey); wpa_hexdump_buf(MSG_DEBUG, "WPS: DH own Public Key", pubkey); wpabuf_put_be16(msg, ATTR_PUBLIC_KEY); wpabuf_put_be16(msg, wpabuf_len(pubkey)); wpabuf_put_buf(msg, pubkey); if (wps->registrar) { wpabuf_free(wps->dh_pubkey_r); wps->dh_pubkey_r = pubkey; } else { wpabuf_free(wps->dh_pubkey_e); wps->dh_pubkey_e = pubkey; } return 0; }
static void eap_mschapv2_copy_challenge(struct eap_mschapv2_data *data, const struct wpabuf *reqData) { wpabuf_free(data->prev_challenge); data->prev_challenge = wpabuf_dup(reqData); }
void * p2p_sd_request(struct p2p_data *p2p, const u8 *dst, const struct wpabuf *tlvs) { struct p2p_sd_query *q; q = os_zalloc(sizeof(*q)); if (q == NULL) return NULL; if (dst) os_memcpy(q->peer, dst, ETH_ALEN); else q->for_all_peers = 1; q->tlvs = wpabuf_dup(tlvs); if (q->tlvs == NULL) { p2p_free_sd_query(q); return NULL; } q->next = p2p->sd_queries; p2p->sd_queries = q; wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Added SD Query %p", q); if (dst == NULL) { struct p2p_device *dev; dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) dev->flags &= ~P2P_DEV_SD_INFO; } return q; }
/** * eap_peer_tls_data_reassemble - Reassemble TLS data * @data: Data for TLS processing * @in_data: Next incoming TLS segment * @need_more_input: Variable for returning whether more input data is needed * to reassemble this TLS packet * Returns: Pointer to output data, %NULL on error or when more data is needed * for the full message (in which case, *need_more_input is also set to 1). * * This function reassembles TLS fragments. Caller must not free the returned * data buffer since an internal pointer to it is maintained. */ static const struct wpabuf * eap_peer_tls_data_reassemble( struct eap_ssl_data *data, const struct wpabuf *in_data, int *need_more_input) { *need_more_input = 0; if (data->tls_in_left > wpabuf_len(in_data) || data->tls_in) { /* Message has fragments */ int res = eap_peer_tls_reassemble_fragment(data, in_data); if (res) { if (res == 1) *need_more_input = 1; return NULL; } /* Message is now fully reassembled. */ } else { /* No fragments in this message, so just make a copy of it. */ data->tls_in_left = 0; data->tls_in = wpabuf_dup(in_data); if (data->tls_in == NULL) return NULL; } return data->tls_in; }
void * p2p_sd_request(struct p2p_data *p2p, const u8 *dst, const struct wpabuf *tlvs) { struct p2p_sd_query *q; q = os_zalloc(sizeof(*q)); if (q == NULL) return NULL; if (dst) os_memcpy(q->peer, dst, ETH_ALEN); else q->for_all_peers = 1; q->tlvs = wpabuf_dup(tlvs); if (q->tlvs == NULL) { p2p_free_sd_query(q); return NULL; } q->next = p2p->sd_queries; p2p->sd_queries = q; wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Added SD Query %p", q); return q; }
/** * event_add - Add a new event to a queue * @s: Subscription * @data: Event data (is copied; caller retains ownership) * Returns: 0 on success, 1 on error */ int event_add(struct subscription *s, const struct wpabuf *data) { struct wps_event_ *e; if (s->n_queue >= MAX_EVENTS_QUEUED) { wpa_printf(MSG_DEBUG, "WPS UPnP: Too many events queued for " "subscriber"); return 1; } e = os_zalloc(sizeof(*e)); if (e == NULL) return 1; e->s = s; e->sd = -1; e->data = wpabuf_dup(data); if (e->data == NULL) { os_free(e); return 1; } e->subscriber_sequence = s->next_subscriber_sequence++; if (s->next_subscriber_sequence == 0) s->next_subscriber_sequence++; event_enqueue_at_end(s, e); event_send_all_later(s->sm); return 0; }
static void pmksa_cache_from_eapol_data(struct rsn_pmksa_cache_entry *entry, struct eapol_state_machine *eapol) { if (eapol == NULL) return; if (eapol->identity) { entry->identity = os_malloc(eapol->identity_len); if (entry->identity) { entry->identity_len = eapol->identity_len; os_memcpy(entry->identity, eapol->identity, eapol->identity_len); } } if (eapol->radius_cui) entry->cui = wpabuf_dup(eapol->radius_cui); #ifndef CONFIG_NO_RADIUS radius_copy_class(&entry->radius_class, &eapol->radius_class); #endif /* CONFIG_NO_RADIUS */ entry->eap_type_authsrv = eapol->eap_type_authsrv; entry->vlan_id = ((struct sta_info *) eapol->sta)->vlan_id; }
void pmksa_cache_to_eapol_data(struct rsn_pmksa_cache_entry *entry, struct eapol_state_machine *eapol) { if (entry == NULL || eapol == NULL) return; if (entry->identity) { os_free(eapol->identity); eapol->identity = os_malloc(entry->identity_len); if (eapol->identity) { eapol->identity_len = entry->identity_len; os_memcpy(eapol->identity, entry->identity, entry->identity_len); } wpa_hexdump_ascii(MSG_DEBUG, "STA identity from PMKSA", eapol->identity, eapol->identity_len); } if (entry->cui) { wpabuf_free(eapol->radius_cui); eapol->radius_cui = wpabuf_dup(entry->cui); } #ifndef CONFIG_NO_RADIUS radius_free_class(&eapol->radius_class); radius_copy_class(&eapol->radius_class, &entry->radius_class); #endif /* CONFIG_NO_RADIUS */ if (eapol->radius_class.attr) { wpa_printf(MSG_DEBUG, "Copied %lu Class attribute(s) from " "PMKSA", (unsigned long) eapol->radius_class.count); } eapol->eap_type_authsrv = entry->eap_type_authsrv; ((struct sta_info *) eapol->sta)->vlan_id = entry->vlan_id; }
struct wpabuf * wps_enrollee_get_msg(struct wps_data *wps, enum wsc_op_code *op_code) { struct wpabuf *msg; switch (wps->state) { case SEND_M1: msg = wps_build_m1(wps); *op_code = WSC_MSG; break; case SEND_M3: msg = wps_build_m3(wps); *op_code = WSC_MSG; break; case SEND_M5: msg = wps_build_m5(wps); *op_code = WSC_MSG; break; case SEND_M7: msg = wps_build_m7(wps); *op_code = WSC_MSG; break; case RECEIVED_M2D: if (wps->wps->ap) { msg = wps_build_wsc_nack(wps); *op_code = WSC_NACK; break; } msg = wps_build_wsc_ack(wps); *op_code = WSC_ACK; if (msg) { /* Another M2/M2D may be received */ wps->state = RECV_M2; } break; case SEND_WSC_NACK: msg = wps_build_wsc_nack(wps); *op_code = WSC_NACK; break; case WPS_MSG_DONE: msg = wps_build_wsc_done(wps); *op_code = WSC_Done; break; default: wpa_printf(MSG_DEBUG, "WPS: Unsupported state %d for building " "a message", wps->state); msg = NULL; break; } if (*op_code == WSC_MSG && msg) { /* Save a copy of the last message for Authenticator derivation */ wpabuf_free(wps->last_msg); wps->last_msg = wpabuf_dup(msg); } return msg; }
static struct wpabuf * eap_eke_build_identity(struct eap_sm *sm, struct eap_eke_data *data, u8 id) { struct wpabuf *msg; size_t plen; wpa_printf(MSG_DEBUG, "EAP-EKE: Request/Identity"); plen = 2 + 4 * 4 + 1 + sm->server_id_len; msg = eap_eke_build_msg(data, id, plen, EAP_EKE_ID); if (msg == NULL) return NULL; wpabuf_put_u8(msg, 4); /* NumProposals */ wpabuf_put_u8(msg, 0); /* Reserved */ /* Proposal - DH Group 16 with AES128-CBC and SHA256 */ wpabuf_put_u8(msg, EAP_EKE_DHGROUP_EKE_16); /* Group Description */ wpabuf_put_u8(msg, EAP_EKE_ENCR_AES128_CBC); /* Encryption */ wpabuf_put_u8(msg, EAP_EKE_PRF_HMAC_SHA2_256); /* PRF */ wpabuf_put_u8(msg, EAP_EKE_MAC_HMAC_SHA2_256); /* MAC */ /* Proposal - DH Group 15 with AES128-CBC and SHA256 */ wpabuf_put_u8(msg, EAP_EKE_DHGROUP_EKE_15); /* Group Description */ wpabuf_put_u8(msg, EAP_EKE_ENCR_AES128_CBC); /* Encryption */ wpabuf_put_u8(msg, EAP_EKE_PRF_HMAC_SHA2_256); /* PRF */ wpabuf_put_u8(msg, EAP_EKE_MAC_HMAC_SHA2_256); /* MAC */ /* Proposal - DH Group 14 with AES128-CBC and SHA256 */ wpabuf_put_u8(msg, EAP_EKE_DHGROUP_EKE_14); /* Group Description */ wpabuf_put_u8(msg, EAP_EKE_ENCR_AES128_CBC); /* Encryption */ wpabuf_put_u8(msg, EAP_EKE_PRF_HMAC_SHA2_256); /* PRF */ wpabuf_put_u8(msg, EAP_EKE_MAC_HMAC_SHA2_256); /* MAC */ /* * Proposal - DH Group 14 with AES128-CBC and SHA1 * (mandatory to implement algorithms) */ wpabuf_put_u8(msg, EAP_EKE_DHGROUP_EKE_14); /* Group Description */ wpabuf_put_u8(msg, EAP_EKE_ENCR_AES128_CBC); /* Encryption */ wpabuf_put_u8(msg, EAP_EKE_PRF_HMAC_SHA1); /* PRF */ wpabuf_put_u8(msg, EAP_EKE_MAC_HMAC_SHA1); /* MAC */ /* Server IDType + Identity */ wpabuf_put_u8(msg, data->serverid_type); wpabuf_put_data(msg, sm->server_id, sm->server_id_len); wpabuf_free(data->msgs); data->msgs = wpabuf_dup(msg); if (data->msgs == NULL) { wpabuf_free(msg); return NULL; } return msg; }
static int eap_copy_buf(struct wpabuf **dst, const struct wpabuf *src) { if (src == NULL) return -1; wpabuf_free(*dst); *dst = wpabuf_dup(src); return *dst ? 0 : -1; }
static int hostapd_rx_req_put_wlan_response( void *priv, enum upnp_wps_wlanevent_type ev_type, const u8 *mac_addr, const struct wpabuf *msg, enum wps_msg_type msg_type) { struct hostapd_data *hapd = priv; struct sta_info *sta; struct upnp_pending_message *p; wpa_printf(MSG_DEBUG, "WPS UPnP: PutWLANResponse ev_type=%d mac_addr=" MACSTR, ev_type, MAC2STR(mac_addr)); wpa_hexdump(MSG_MSGDUMP, "WPS UPnP: PutWLANResponse NewMessage", wpabuf_head(msg), wpabuf_len(msg)); if (ev_type != UPNP_WPS_WLANEVENT_TYPE_EAP) { wpa_printf(MSG_DEBUG, "WPS UPnP: Ignored unexpected " "PutWLANResponse WLANEventType %d", ev_type); return -1; } /* * EAP response to ongoing to WPS Registration. Send it to EAP-WSC * server implementation for delivery to the peer. */ sta = ap_get_sta(hapd, mac_addr); #ifndef CONFIG_WPS_STRICT if (!sta) { /* * Workaround - Intel wsccmd uses bogus NewWLANEventMAC: * Pick STA that is in an ongoing WPS registration without * checking the MAC address. */ wpa_printf(MSG_DEBUG, "WPS UPnP: No matching STA found based " "on NewWLANEventMAC; try wildcard match"); for (sta = hapd->sta_list; sta; sta = sta->next) { if (sta->eapol_sm && (sta->flags & WLAN_STA_WPS)) break; } } #endif /* CONFIG_WPS_STRICT */ if (!sta || !(sta->flags & WLAN_STA_WPS)) { wpa_printf(MSG_DEBUG, "WPS UPnP: No matching STA found"); return 0; } p = os_zalloc(sizeof(*p)); if (p == NULL) return -1; os_memcpy(p->addr, sta->addr, ETH_ALEN); p->msg = wpabuf_dup(msg); p->type = msg_type; p->next = hapd->wps->upnp_msgs; hapd->wps->upnp_msgs = p; return eapol_auth_eap_pending_cb(sta->eapol_sm, sta->eapol_sm->eap); }
static void eap_mschapv2_copy_challenge(struct eap_mschapv2_data *data, const struct wpabuf *reqData) { /* * Store a copy of the challenge message, so that it can be processed * again in case retry is allowed after a possible failure. */ wpabuf_free(data->prev_challenge); data->prev_challenge = wpabuf_dup(reqData); }
int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg) { struct wpabuf *pubkey; wpa_printf(MSG_DEBUG, "WPS: * Public Key"); wpabuf_free(wps->dh_privkey); //if (wps->dev_pw_id != DEV_PW_DEFAULT && wps->wps->dh_privkey) { if (wps->wps->dh_privkey) { wpa_printf(MSG_DEBUG, "WPS: Using pre-configured DH keys"); wps->dh_privkey = wpabuf_dup(wps->wps->dh_privkey); wps->dh_ctx = wps->wps->dh_ctx; wps->wps->dh_ctx = NULL; pubkey = wpabuf_dup(wps->wps->dh_pubkey); } else { wpa_printf(MSG_DEBUG, "WPS: Generate new DH keys"); wps->dh_privkey = NULL; dh5_free(wps->dh_ctx); wps->dh_ctx = dh5_init(&wps->dh_privkey, &pubkey); pubkey = wpabuf_zeropad(pubkey, 192); } if (wps->dh_ctx == NULL || wps->dh_privkey == NULL || pubkey == NULL) { wpa_printf(MSG_DEBUG, "WPS: Failed to initialize " "Diffie-Hellman handshake"); wpabuf_free(pubkey); return -1; } wpabuf_put_be16(msg, ATTR_PUBLIC_KEY); wpabuf_put_be16(msg, wpabuf_len(pubkey)); wpabuf_put_buf(msg, pubkey); if (wps->registrar) { wpabuf_free(wps->dh_pubkey_r); wps->dh_pubkey_r = pubkey; } else { wpabuf_free(wps->dh_pubkey_e); wps->dh_pubkey_e = pubkey; } return 0; }
int hostapd_neighbor_set(struct hostapd_data *hapd, const u8 *bssid, const struct wpa_ssid_value *ssid, const struct wpabuf *nr, const struct wpabuf *lci, const struct wpabuf *civic, int stationary) { struct hostapd_neighbor_entry *entry; entry = hostapd_neighbor_get(hapd, bssid, ssid); if (!entry) entry = hostapd_neighbor_add(hapd); if (!entry) return -1; hostapd_neighbor_clear_entry(entry); os_memcpy(entry->bssid, bssid, ETH_ALEN); os_memcpy(&entry->ssid, ssid, sizeof(entry->ssid)); entry->nr = wpabuf_dup(nr); if (!entry->nr) goto fail; if (lci && wpabuf_len(lci)) { entry->lci = wpabuf_dup(lci); if (!entry->lci || os_get_time(&entry->lci_date)) goto fail; } if (civic && wpabuf_len(civic)) { entry->civic = wpabuf_dup(civic); if (!entry->civic) goto fail; } entry->stationary = stationary; return 0; fail: hostapd_neighbor_remove(hapd, bssid, ssid); return -1; }
void p2p_sd_response(struct p2p_data *p2p, int freq, const u8 *dst, u8 dialog_token, const struct wpabuf *resp_tlvs) { struct wpabuf *resp; size_t max_len; /* * In the 60 GHz, we have a smaller maximum frame length for management * frames. */ max_len = (freq > 56160) ? 928 : 1400; /* TODO: fix the length limit to match with the maximum frame length */ if (wpabuf_len(resp_tlvs) > max_len) { p2p_dbg(p2p, "SD response long enough to require fragmentation"); if (p2p->sd_resp) { /* * TODO: Could consider storing the fragmented response * separately for each peer to avoid having to drop old * one if there is more than one pending SD query. * Though, that would eat more memory, so there are * also benefits to just using a single buffer. */ p2p_dbg(p2p, "Drop previous SD response"); wpabuf_free(p2p->sd_resp); } p2p->sd_resp = wpabuf_dup(resp_tlvs); if (p2p->sd_resp == NULL) { p2p_err(p2p, "Failed to allocate SD response fragmentation area"); return; } os_memcpy(p2p->sd_resp_addr, dst, ETH_ALEN); p2p->sd_resp_dialog_token = dialog_token; p2p->sd_resp_pos = 0; p2p->sd_frag_id = 0; resp = p2p_build_sd_response(dialog_token, WLAN_STATUS_SUCCESS, 1, p2p->srv_update_indic, NULL); } else { p2p_dbg(p2p, "SD response fits in initial response"); resp = p2p_build_sd_response(dialog_token, WLAN_STATUS_SUCCESS, 0, p2p->srv_update_indic, resp_tlvs); } if (resp == NULL) return; p2p->pending_action_state = P2P_NO_PENDING_ACTION; if (p2p_send_action(p2p, freq, dst, p2p->cfg->dev_addr, p2p->cfg->dev_addr, wpabuf_head(resp), wpabuf_len(resp), 200) < 0) p2p_dbg(p2p, "Failed to send Action frame"); wpabuf_free(resp); }
int wpas_ap_wps_add_nfc_pw(struct wpa_supplicant *wpa_s, u16 pw_id, const struct wpabuf *pw, const u8 *pubkey_hash) { struct hostapd_data *hapd; struct wps_context *wps; if (!wpa_s->ap_iface) return -1; hapd = wpa_s->ap_iface->bss[0]; wps = hapd->wps; if (wpa_s->p2pdev->conf->wps_nfc_dh_pubkey == NULL || wpa_s->p2pdev->conf->wps_nfc_dh_privkey == NULL) { wpa_printf(MSG_DEBUG, "P2P: No NFC DH key known"); return -1; } dh5_free(wps->dh_ctx); wpabuf_free(wps->dh_pubkey); wpabuf_free(wps->dh_privkey); wps->dh_privkey = wpabuf_dup( wpa_s->p2pdev->conf->wps_nfc_dh_privkey); wps->dh_pubkey = wpabuf_dup( wpa_s->p2pdev->conf->wps_nfc_dh_pubkey); if (wps->dh_privkey == NULL || wps->dh_pubkey == NULL) { wps->dh_ctx = NULL; wpabuf_free(wps->dh_pubkey); wps->dh_pubkey = NULL; wpabuf_free(wps->dh_privkey); wps->dh_privkey = NULL; return -1; } wps->dh_ctx = dh5_init_fixed(wps->dh_privkey, wps->dh_pubkey); if (wps->dh_ctx == NULL) return -1; return wps_registrar_add_nfc_pw_token(hapd->wps->registrar, pubkey_hash, pw_id, pw ? wpabuf_head(pw) : NULL, pw ? wpabuf_len(pw) : 0, 1); }
int hostapd_wps_nfc_token_enable(struct hostapd_data *hapd) { struct wps_context *wps = hapd->wps; struct wpabuf *pw; if (wps == NULL) return -1; if (!hapd->conf->wps_nfc_dh_pubkey || !hapd->conf->wps_nfc_dh_privkey || !hapd->conf->wps_nfc_dev_pw || !hapd->conf->wps_nfc_dev_pw_id) return -1; hostapd_wps_nfc_clear(wps); wpa_printf(MSG_DEBUG, "WPS: Enable NFC Tag (Dev Pw Id %u) for AP interface %s (context %p)", hapd->conf->wps_nfc_dev_pw_id, hapd->conf->iface, wps); wps->ap_nfc_dev_pw_id = hapd->conf->wps_nfc_dev_pw_id; wps->ap_nfc_dh_pubkey = wpabuf_dup(hapd->conf->wps_nfc_dh_pubkey); wps->ap_nfc_dh_privkey = wpabuf_dup(hapd->conf->wps_nfc_dh_privkey); pw = hapd->conf->wps_nfc_dev_pw; wps->ap_nfc_dev_pw = wpabuf_alloc( wpabuf_len(pw) * 2 + 1); if (wps->ap_nfc_dev_pw) { wpa_snprintf_hex_uppercase( (char *) wpabuf_put(wps->ap_nfc_dev_pw, wpabuf_len(pw) * 2), wpabuf_len(pw) * 2 + 1, wpabuf_head(pw), wpabuf_len(pw)); } if (!wps->ap_nfc_dh_pubkey || !wps->ap_nfc_dh_privkey || !wps->ap_nfc_dev_pw) { hostapd_wps_nfc_clear(wps); return -1; } return 0; }
void p2p_sd_response(struct p2p_data *p2p, int freq, const u8 *dst, u8 dialog_token, const struct wpabuf *resp_tlvs) { struct wpabuf *resp; /* TODO: fix the length limit to match with the maximum frame length */ if (wpabuf_len(resp_tlvs) > 1400) { wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: SD response long " "enough to require fragmentation"); if (p2p->sd_resp) { /* * TODO: Could consider storing the fragmented response * separately for each peer to avoid having to drop old * one if there is more than one pending SD query. * Though, that would eat more memory, so there are * also benefits to just using a single buffer. */ wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Drop " "previous SD response"); wpabuf_free(p2p->sd_resp); } p2p->sd_resp = wpabuf_dup(resp_tlvs); if (p2p->sd_resp == NULL) { wpa_msg(p2p->cfg->msg_ctx, MSG_ERROR, "P2P: Failed to " "allocate SD response fragmentation area"); return; } os_memcpy(p2p->sd_resp_addr, dst, ETH_ALEN); p2p->sd_resp_dialog_token = dialog_token; p2p->sd_resp_pos = 0; p2p->sd_frag_id = 0; resp = p2p_build_sd_response(dialog_token, WLAN_STATUS_SUCCESS, 1, p2p->srv_update_indic, NULL); } else { wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: SD response fits " "in initial response"); resp = p2p_build_sd_response(dialog_token, WLAN_STATUS_SUCCESS, 0, p2p->srv_update_indic, resp_tlvs); } if (resp == NULL) return; p2p->pending_action_state = P2P_NO_PENDING_ACTION; if (p2p_send_action(p2p, freq, dst, p2p->cfg->dev_addr, p2p->cfg->dev_addr, wpabuf_head(resp), wpabuf_len(resp), 200) < 0) wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Failed to send Action frame"); wpabuf_free(resp); }
static int ar6000_set_ap_wps_ie(void *priv, const struct wpabuf *beacon, const struct wpabuf *proberesp, const struct wpabuf *assocresp) { struct ar6000_driver_data *drv = priv; wpabuf_free(drv->wps_beacon_ie); drv->wps_beacon_ie = beacon ? wpabuf_dup(beacon) : NULL; wpabuf_free(drv->wps_probe_resp_ie); drv->wps_probe_resp_ie = proberesp ? wpabuf_dup(proberesp) : NULL; ar6000_set_wps_ie(drv, assocresp ? wpabuf_head(assocresp) : NULL, assocresp ? wpabuf_len(assocresp) : 0, IEEE80211_APPIE_FRAME_ASSOC_RESP); if (ar6000_set_wps_ie(drv, beacon ? wpabuf_head(beacon) : NULL, beacon ? wpabuf_len(beacon) : 0, IEEE80211_APPIE_FRAME_BEACON)) return -1; return ar6000_set_wps_ie(drv, proberesp ? wpabuf_head(proberesp) : NULL, proberesp ? wpabuf_len(proberesp): 0, IEEE80211_APPIE_FRAME_PROBE_RESP); }
/** * event_add - Add a new event to a queue * @s: Subscription * @data: Event data (is copied; caller retains ownership) * @probereq: Whether this is a Probe Request event * Returns: 0 on success, -1 on error, 1 on max event queue limit reached */ int event_add(struct subscription *s, const struct wpabuf *data, int probereq) { struct wps_event_ *e; unsigned int len; len = dl_list_len(&s->event_queue); if (len >= MAX_EVENTS_QUEUED) { wpa_printf(MSG_DEBUG, "WPS UPnP: Too many events queued for " "subscriber %p", s); if (probereq) return 1; /* Drop oldest entry to allow EAP event to be stored. */ e = event_dequeue(s); if (!e) return 1; event_delete(e); } if (s->last_event_failed && probereq && len > 0) { /* * Avoid queuing frames for subscribers that may have left * without unsubscribing. */ wpa_printf(MSG_DEBUG, "WPS UPnP: Do not queue more Probe " "Request frames for subscription %p since last " "delivery failed", s); return -1; } e = os_zalloc(sizeof(*e)); if (e == NULL) return -1; dl_list_init(&e->list); e->s = s; e->data = wpabuf_dup(data); if (e->data == NULL) { os_free(e); return -1; } e->subscriber_sequence = s->next_subscriber_sequence++; if (s->next_subscriber_sequence == 0) s->next_subscriber_sequence++; wpa_printf(MSG_DEBUG, "WPS UPnP: Queue event %p for subscriber %p " "(queue len %u)", e, s, len + 1); dl_list_add_tail(&s->event_queue, &e->list); event_send_all_later(s->sm); return 0; }
static int eap_aka_add_id_msg(struct eap_aka_data *data, const struct wpabuf *msg) { if (msg == NULL) return -1; if (data->id_msgs == NULL) { data->id_msgs = wpabuf_dup(msg); return data->id_msgs == NULL ? -1 : 0; } if (wpabuf_resize(&data->id_msgs, wpabuf_len(msg)) < 0) return -1; wpabuf_put_buf(data->id_msgs, msg); return 0; }
void * p2p_sd_request(struct p2p_data *p2p, const u8 *dst, const struct wpabuf *tlvs) { struct p2p_sd_query *q; #ifdef ANDROID_P2P /* Currently, supplicant doesn't support more than one pending broadcast SD request. * So reject if application is registering another one before cancelling the existing one. */ for (q = p2p->sd_queries; q; q = q->next) { if( (q->for_all_peers == 1) && (!dst)) { wpa_printf(MSG_ERROR, "P2P: Already one pending" " Broadcast request. Please cancel the current one" " before adding a new one"); return NULL; } } #endif q = os_zalloc(sizeof(*q)); if (q == NULL) return NULL; if (dst) os_memcpy(q->peer, dst, ETH_ALEN); else q->for_all_peers = 1; q->tlvs = wpabuf_dup(tlvs); if (q->tlvs == NULL) { p2p_free_sd_query(q); return NULL; } q->next = p2p->sd_queries; p2p->sd_queries = q; wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Added SD Query %p for_all_peers %d", q, q->for_all_peers); if (dst == NULL) { struct p2p_device *dev; dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) dev->flags &= ~P2P_DEV_SD_INFO; } return q; }
struct rsn_pmksa_cache_entry * pmksa_cache_add_okc(struct rsn_pmksa_cache *pmksa, const struct rsn_pmksa_cache_entry *old_entry, const u8 *aa, const u8 *pmkid) { struct rsn_pmksa_cache_entry *entry; entry = os_zalloc(sizeof(*entry)); if (entry == NULL) return NULL; os_memcpy(entry->pmkid, pmkid, PMKID_LEN); os_memcpy(entry->pmk, old_entry->pmk, old_entry->pmk_len); entry->pmk_len = old_entry->pmk_len; entry->expiration = old_entry->expiration; entry->akmp = old_entry->akmp; os_memcpy(entry->spa, old_entry->spa, ETH_ALEN); entry->opportunistic = 1; if (old_entry->identity) { entry->identity = os_malloc(old_entry->identity_len); if (entry->identity) { entry->identity_len = old_entry->identity_len; os_memcpy(entry->identity, old_entry->identity, old_entry->identity_len); } } if (old_entry->cui) entry->cui = wpabuf_dup(old_entry->cui); #ifndef CONFIG_NO_RADIUS radius_copy_class(&entry->radius_class, &old_entry->radius_class); #endif /* CONFIG_NO_RADIUS */ entry->eap_type_authsrv = old_entry->eap_type_authsrv; if (old_entry->vlan_desc) { entry->vlan_desc = os_zalloc(sizeof(struct vlan_description)); if (entry->vlan_desc) *entry->vlan_desc = *old_entry->vlan_desc; } else { entry->vlan_desc = NULL; } entry->opportunistic = 1; pmksa_cache_link_entry(pmksa, entry); return entry; }
void * p2p_sd_request(struct p2p_data *p2p, const u8 *dst, const struct wpabuf *tlvs) { struct p2p_sd_query *q; q = os_zalloc(sizeof(*q)); if (q == NULL) return NULL; if (dst) os_memcpy(q->peer, dst, ETH_ALEN); else q->for_all_peers = 1; q->tlvs = wpabuf_dup(tlvs); if (q->tlvs == NULL) { p2p_free_sd_query(q); return NULL; } q->next = p2p->sd_queries; p2p->sd_queries = q; p2p_dbg(p2p, "Added SD Query %p", q); if (dst == NULL) { struct p2p_device *dev; p2p->num_p2p_sd_queries++; /* Update all the devices for the newly added broadcast query */ dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) { #ifdef CONFIG_MTK_P2P dev->flags &= ~P2P_DEV_SD_INFO; #endif if (dev->sd_pending_bcast_queries <= 0) dev->sd_pending_bcast_queries = 1; else dev->sd_pending_bcast_queries++; } } return q; }
static struct wpabuf * p2p_group_build_probe_resp_ie(struct p2p_group *group) { struct wpabuf *p2p_subelems, *ie; struct p2p_group_member *m; p2p_subelems = wpabuf_alloc(500); if (p2p_subelems == NULL) return NULL; p2p_group_add_common_ies(group, p2p_subelems); p2p_group_add_noa(p2p_subelems, group->noa); /* P2P Device Info */ p2p_buf_add_device_info(p2p_subelems, group->p2p, NULL); /* P2P Group Info: Only when at least one P2P Client is connected */ if (group->members) { u8 *group_info; group_info = wpabuf_put(p2p_subelems, 0); wpabuf_put_u8(p2p_subelems, P2P_ATTR_GROUP_INFO); wpabuf_put_le16(p2p_subelems, 0); /* Length to be filled */ for (m = group->members; m; m = m->next) p2p_client_info(p2p_subelems, m); WPA_PUT_LE16(group_info + 1, (u8 *) wpabuf_put(p2p_subelems, 0) - group_info - 3); } ie = p2p_group_encaps_probe_resp(p2p_subelems); wpabuf_free(p2p_subelems); #ifdef CONFIG_WIFI_DISPLAY if (group->wfd_ie) { struct wpabuf *wfd = wpabuf_dup(group->wfd_ie); ie = wpabuf_concat(wfd, ie); } #endif /* CONFIG_WIFI_DISPLAY */ return ie; }
struct wpabuf * tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data) { ssize_t res; struct wpabuf *out; if (conn->pull_buf) { wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in " "pull_buf", __func__, (unsigned long) wpabuf_len(conn->pull_buf)); wpabuf_free(conn->pull_buf); } conn->pull_buf = wpabuf_dup(in_data); if (conn->pull_buf == NULL) return NULL; conn->pull_buf_offset = wpabuf_head(conn->pull_buf); /* * Even though we try to disable TLS compression, it is possible that * this cannot be done with all TLS libraries. Add extra buffer space * to handle the possibility of the decrypted data being longer than * input data. */ out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3); if (out == NULL) return NULL; res = gnutls_record_recv(conn->session, wpabuf_mhead(out), wpabuf_size(out)); if (res < 0) { wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d " "(%s)", __func__, (int) res, gnutls_strerror(res)); wpabuf_free(out); return NULL; } wpabuf_put(out, res); return out; }
int wpa_driver_set_ap_wps_p2p_ie(void *priv, const struct wpabuf *beacon, const struct wpabuf *proberesp, const struct wpabuf *assocresp) { char buf[MAX_WPSP2PIE_CMD_SIZE]; struct wpabuf *ap_wps_p2p_ie = NULL; char *_cmd = "SET_AP_WPS_P2P_IE"; char *pbuf; int ret = 0; int i; struct cmd_desc { int cmd; const struct wpabuf *src; } cmd_arr[] = { {0x1, beacon}, {0x2, proberesp}, {0x4, assocresp}, {-1, NULL} }; wpa_printf(MSG_DEBUG, "%s: Entry", __func__); for (i = 0; cmd_arr[i].cmd != -1; i++) { os_memset(buf, 0, sizeof(buf)); pbuf = buf; pbuf += sprintf(pbuf, "%s %d", _cmd, cmd_arr[i].cmd); *pbuf++ = '\0'; ap_wps_p2p_ie = cmd_arr[i].src ? wpabuf_dup(cmd_arr[i].src) : NULL; if (ap_wps_p2p_ie) { os_memcpy(pbuf, wpabuf_head(ap_wps_p2p_ie), wpabuf_len(ap_wps_p2p_ie)); ret = wpa_driver_nl80211_driver_cmd(priv, buf, buf, strlen(_cmd) + 3 + wpabuf_len(ap_wps_p2p_ie)); wpabuf_free(ap_wps_p2p_ie); if (ret < 0) break; } } return ret; }