static struct wpabuf * wps_build_m1(struct wps_data *wps) { struct wpabuf *msg; u16 config_methods; if (random_get_bytes(wps->nonce_e, WPS_NONCE_LEN) < 0) return NULL; wpa_hexdump(MSG_DEBUG, "WPS: Enrollee Nonce", wps->nonce_e, WPS_NONCE_LEN); wpa_printf(MSG_DEBUG, "WPS: Building Message M1"); msg = wpabuf_alloc(1000); if (msg == NULL) return NULL; config_methods = wps->wps->config_methods; if (wps->wps->ap && !wps->pbc_in_m1 && (wps->dev_password_len != 0 || (config_methods & WPS_CONFIG_DISPLAY))) { /* * These are the methods that the AP supports as an Enrollee * for adding external Registrars, so remove PushButton. * * As a workaround for Windows 7 mechanism for probing WPS * capabilities from M1, leave PushButton option if no PIN * method is available or if WPS configuration enables PBC * workaround. */ config_methods &= ~WPS_CONFIG_PUSHBUTTON; config_methods &= ~(WPS_CONFIG_VIRT_PUSHBUTTON | WPS_CONFIG_PHY_PUSHBUTTON); } if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_M1) || wps_build_uuid_e(msg, wps->uuid_e) || wps_build_mac_addr(msg, wps->mac_addr_e) || wps_build_enrollee_nonce(wps, msg) || wps_build_public_key(wps, msg) || wps_build_auth_type_flags(wps, msg) || wps_build_encr_type_flags(wps, msg) || wps_build_conn_type_flags(wps, msg) || wps_build_config_methods(msg, config_methods) || wps_build_wps_state(wps, msg) || wps_build_device_attrs(&wps->wps->dev, msg) || wps_build_rf_bands(&wps->wps->dev, msg, wps->wps->rf_band_cb(wps->wps->cb_ctx)) || wps_build_assoc_state(wps, msg) || wps_build_dev_password_id(msg, wps->dev_pw_id) || wps_build_config_error(msg, WPS_CFG_NO_ERROR) || wps_build_os_version(&wps->wps->dev, msg) || wps_build_wfa_ext(msg, 0, NULL, 0) || wps_build_vendor_ext_m1(&wps->wps->dev, msg)) { wpabuf_free(msg); return NULL; } wps->state = RECV_M2; return msg; }
/** * wps_build_assoc_resp_ie - Build WPS IE for (Re)Association Response * Returns: WPS IE or %NULL on failure * * The caller is responsible for freeing the buffer. */ struct wpabuf * wps_build_assoc_resp_ie(void) { struct wpabuf *ie; u8 *len; wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for (Re)Association " "Response"); ie = wpabuf_alloc(100); if (ie == NULL) return NULL; wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC); len = wpabuf_put(ie, 1); wpabuf_put_be32(ie, WPS_DEV_OUI_WFA); if (wps_build_version(ie) || wps_build_resp_type(ie, WPS_RESP_AP) || wps_build_wfa_ext(ie, 0, NULL, 0)) { wpabuf_free(ie); return NULL; } *len = wpabuf_len(ie) - 2; return ie; }
static struct wpabuf * wps_build_wsc_done(struct wps_data *wps) { struct wpabuf *msg; wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_Done"); msg = wpabuf_alloc(1000); if (msg == NULL) return NULL; if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_WSC_DONE) || wps_build_enrollee_nonce(wps, msg) || wps_build_registrar_nonce(wps, msg) || wps_build_wfa_ext(msg, 0, NULL, 0)) { wpabuf_free(msg); return NULL; } if (wps->wps->ap) wps->state = RECV_ACK; else { wps_success_event(wps->wps); wps->state = WPS_FINISHED; } return msg; }
static struct wpabuf * wps_build_m3(struct wps_data *wps) { struct wpabuf *msg; wpa_printf(MSG_DEBUG, "WPS: Building Message M3"); if (wps->dev_password == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Device Password available"); return NULL; } wps_derive_psk(wps, wps->dev_password, wps->dev_password_len); msg = wpabuf_alloc(1000); if (msg == NULL) return NULL; if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_M3) || wps_build_registrar_nonce(wps, msg) || wps_build_e_hash(wps, msg) || wps_build_wfa_ext(msg, 0, NULL, 0) || wps_build_authenticator(wps, msg)) { wpabuf_free(msg); return NULL; } wps->state = RECV_M4; return msg; }
void wps_er_set_sel_reg(struct wps_er *er, int sel_reg, u16 dev_passwd_id, u16 sel_reg_config_methods) { struct wpabuf *msg; struct wps_er_ap *ap; struct wps_registrar *reg = er->wps->registrar; const u8 *auth_macs; #ifdef CONFIG_WPS2 u8 bcast[ETH_ALEN]; #endif /* CONFIG_WPS2 */ size_t count; union wps_event_data data; if (er->skip_set_sel_reg) { wpa_printf(MSG_DEBUG, "WPS ER: Skip SetSelectedRegistrar"); return; } msg = wpabuf_alloc(500); if (msg == NULL) return; auth_macs = wps_authorized_macs(reg, &count); #ifdef CONFIG_WPS2 if (count == 0) { os_memset(bcast, 0xff, ETH_ALEN); auth_macs = bcast; count = 1; } #endif /* CONFIG_WPS2 */ if (wps_build_version(msg) || wps_er_build_selected_registrar(msg, sel_reg) || wps_er_build_dev_password_id(msg, dev_passwd_id) || wps_er_build_sel_reg_config_methods(msg, sel_reg_config_methods) || wps_build_wfa_ext(msg, 0, auth_macs, count) || wps_er_build_uuid_r(msg, er->wps->uuid)) { wpabuf_free(msg); return; } os_memset(&data, 0, sizeof(data)); data.set_sel_reg.sel_reg = sel_reg; data.set_sel_reg.dev_passwd_id = dev_passwd_id; data.set_sel_reg.sel_reg_config_methods = sel_reg_config_methods; data.set_sel_reg.state = WPS_ER_SET_SEL_REG_START; dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) { if (er->set_sel_reg_uuid_filter && os_memcmp(ap->uuid, er->set_sel_reg_uuid_filter, WPS_UUID_LEN) != 0) continue; data.set_sel_reg.uuid = ap->uuid; er->wps->event_cb(er->wps->cb_ctx, WPS_EV_ER_SET_SELECTED_REGISTRAR, &data); wps_er_send_set_sel_reg(ap, msg); } wpabuf_free(msg); }
static struct wpabuf * wps_get_oob_cred(struct wps_context *wps) { struct wps_data data; struct wpabuf *plain; plain = wpabuf_alloc(500); if (plain == NULL) { wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB " "credential"); return NULL; } os_memset(&data, 0, sizeof(data)); data.wps = wps; data.auth_type = wps->auth_types; data.encr_type = wps->encr_types; if (wps_build_version(plain) || wps_build_cred(&data, plain) || wps_build_wfa_ext(plain, 0, NULL, 0)) { wpabuf_free(plain); return NULL; } return plain; }
/** * wps_build_assoc_req_ie - Build WPS IE for (Re)Association Request * @req_type: Value for Request Type attribute * Returns: WPS IE or %NULL on failure * * The caller is responsible for freeing the buffer. */ struct wpabuf * wps_build_assoc_req_ie(enum wps_request_type req_type) { struct wpabuf *ie; u8 *len; wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for (Re)Association " "Request"); ie = wpabuf_alloc(100); if (ie == NULL) return NULL; wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC); len = wpabuf_put(ie, 1); wpabuf_put_be32(ie, WPS_DEV_OUI_WFA); if (wps_build_version(ie) || wps_build_req_type(ie, req_type)) { wpabuf_free(ie); return NULL; } *len = wpabuf_len(ie) - 2; return ie; }
static struct wpabuf * wps_get_oob_dev_pwd(struct wps_context *wps) { struct wpabuf *data; data = wpabuf_alloc(9 + WPS_OOB_DEVICE_PASSWORD_ATTR_LEN); if (data == NULL) { wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB " "device password attribute"); return NULL; } wpabuf_free(wps->oob_conf.dev_password); wps->oob_conf.dev_password = wpabuf_alloc(WPS_OOB_DEVICE_PASSWORD_LEN * 2 + 1); if (wps->oob_conf.dev_password == NULL) { wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB " "device password"); wpabuf_free(data); return NULL; } if (wps_build_version(data) || wps_build_oob_dev_password(data, wps) || wps_build_wfa_ext(data, 0, NULL, 0)) { wpa_printf(MSG_ERROR, "WPS: Build OOB device password " "attribute error"); wpabuf_free(data); return NULL; } return data; }
static struct wpabuf * wps_build_m7(struct wps_data *wps) { struct wpabuf *msg, *plain; wpa_printf(MSG_DEBUG, "WPS: Building Message M7"); plain = wpabuf_alloc(500 + wps->wps->ap_settings_len); if (plain == NULL) return NULL; msg = wpabuf_alloc(1000 + wps->wps->ap_settings_len); if (msg == NULL) { wpabuf_free(plain); return NULL; } if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_M7) || wps_build_registrar_nonce(wps, msg) || wps_build_e_snonce2(wps, plain) || (wps->wps->ap && wps_build_ap_settings(wps, plain)) || wps_build_key_wrap_auth(wps, plain) || wps_build_encr_settings(wps, msg, plain) || wps_build_authenticator(wps, msg)) { wpabuf_free(plain); wpabuf_free(msg); return NULL; } wpabuf_free(plain); wps->state = RECV_M8; return msg; }
static struct wpabuf * wps_build_m5(struct wps_data *wps) { struct wpabuf *msg, *plain; wpa_printf(MSG_DEBUG, "WPS: Building Message M5"); plain = wpabuf_alloc(200); if (plain == NULL) return NULL; msg = wpabuf_alloc(1000); if (msg == NULL) { wpabuf_free(plain); return NULL; } if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_M5) || wps_build_registrar_nonce(wps, msg) || wps_build_e_snonce1(wps, plain) || wps_build_key_wrap_auth(wps, plain) || wps_build_encr_settings(wps, msg, plain) || wps_build_wfa_ext(msg, 0, NULL, 0) || wps_build_authenticator(wps, msg)) { wpabuf_free(plain); wpabuf_free(msg); return NULL; } wpabuf_free(plain); wps->state = RECV_M6; return msg; }
void p2p_build_wps_ie(struct p2p_data *p2p, struct wpabuf *buf, u16 pw_id, int all_attr) { u8 *len; wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC); len = wpabuf_put(buf, 1); wpabuf_put_be32(buf, WPS_DEV_OUI_WFA); wps_build_version(buf); if (all_attr) { wpabuf_put_be16(buf, ATTR_WPS_STATE); wpabuf_put_be16(buf, 1); wpabuf_put_u8(buf, WPS_STATE_NOT_CONFIGURED); } /* Device Password ID */ wpabuf_put_be16(buf, ATTR_DEV_PASSWORD_ID); wpabuf_put_be16(buf, 2); wpa_printf(MSG_DEBUG, "P2P: WPS IE Device Password ID: %d", pw_id); wpabuf_put_be16(buf, pw_id); if (all_attr) { size_t nlen; wpabuf_put_be16(buf, ATTR_RESPONSE_TYPE); wpabuf_put_be16(buf, 1); wpabuf_put_u8(buf, WPS_RESP_ENROLLEE_INFO); #if 0 /* FIX */ wps_build_uuid_e(buf, reg->wps->uuid); wps_build_manufacturer(dev, buf); wps_build_model_name(dev, buf); wps_build_model_number(dev, buf); wps_build_serial_number(dev, buf); #endif wpabuf_put_be16(buf, ATTR_PRIMARY_DEV_TYPE); wpabuf_put_be16(buf, WPS_DEV_TYPE_LEN); wpabuf_put_data(buf, p2p->cfg->pri_dev_type, WPS_DEV_TYPE_LEN); wpabuf_put_be16(buf, ATTR_DEV_NAME); nlen = p2p->cfg->dev_name ? os_strlen(p2p->cfg->dev_name) : 0; wpabuf_put_be16(buf, nlen); if (p2p->cfg->dev_name) wpabuf_put_data(buf, p2p->cfg->dev_name, nlen); wpabuf_put_be16(buf, ATTR_CONFIG_METHODS); wpabuf_put_be16(buf, 2); wpabuf_put_be16(buf, 0); /* FIX: ? */ } wps_build_wfa_ext(buf, 0, NULL, 0); p2p_buf_update_ie_hdr(buf, len); }
struct wpabuf * wps_get_oob_cred(struct wps_context *wps) { struct wps_data data; struct wpabuf *plain; plain = wpabuf_alloc(500); if (plain == NULL) { wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB " "credential"); return NULL; } os_memset(&data, 0, sizeof(data)); data.wps = wps; data.auth_type = wps->auth_types; data.encr_type = wps->encr_types; if (wps_build_version(plain) || wps_build_cred(&data, plain) || wps_build_wfa_ext(plain, 0, NULL, 0)) { os_free(data.new_psk); wpabuf_free(plain); return NULL; } if (wps->wps_state == WPS_STATE_NOT_CONFIGURED && data.new_psk && wps->ap) { struct wps_credential cred; wpa_printf(MSG_DEBUG, "WPS: Moving to Configured state based " "on credential token generation"); os_memset(&cred, 0, sizeof(cred)); os_memcpy(cred.ssid, wps->ssid, wps->ssid_len); cred.ssid_len = wps->ssid_len; cred.auth_type = WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK; cred.encr_type = WPS_ENCR_TKIP | WPS_ENCR_AES; os_memcpy(cred.key, data.new_psk, data.new_psk_len); cred.key_len = data.new_psk_len; wps->wps_state = WPS_STATE_CONFIGURED; wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: Generated random passphrase", data.new_psk, data.new_psk_len); if (wps->cred_cb) wps->cred_cb(wps->cb_ctx, &cred); } os_free(data.new_psk); return plain; }
/** * wps_build_probe_req_ie - Build WPS IE for Probe Request * @pbc: Whether searching for PBC mode APs * @dev: Device attributes * @uuid: Own UUID * @req_type: Value for Request Type attribute * @num_req_dev_types: Number of requested device types * @req_dev_types: Requested device types (8 * num_req_dev_types octets) or * %NULL if none * Returns: WPS IE or %NULL on failure * * The caller is responsible for freeing the buffer. */ struct wpabuf * wps_build_probe_req_ie(int pbc, struct wps_device_data *dev, const u8 *uuid, enum wps_request_type req_type, unsigned int num_req_dev_types, const u8 *req_dev_types) { struct wpabuf *ie; wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for Probe Request"); ie = wpabuf_alloc(500); if (ie == NULL) return NULL; if (wps_build_version(ie) || wps_build_req_type(ie, req_type) || wps_build_config_methods(ie, dev->config_methods) || wps_build_uuid_e(ie, uuid) || wps_build_primary_dev_type(dev, ie) || wps_build_rf_bands(dev, ie) || wps_build_assoc_state(NULL, ie) || wps_build_config_error(ie, WPS_CFG_NO_ERROR) || wps_build_dev_password_id(ie, pbc ? DEV_PW_PUSHBUTTON : DEV_PW_DEFAULT) || #ifdef CONFIG_WPS2 wps_build_manufacturer(dev, ie) || wps_build_model_name(dev, ie) || wps_build_model_number(dev, ie) || wps_build_dev_name(dev, ie) || wps_build_wfa_ext(ie, req_type == WPS_REQ_ENROLLEE, NULL, 0) || #endif /* CONFIG_WPS2 */ wps_build_req_dev_type(dev, ie, num_req_dev_types, req_dev_types) || wps_build_secondary_dev_type(dev, ie) ) { wpabuf_free(ie); return NULL; } #ifndef CONFIG_WPS2 if (dev->p2p && wps_build_dev_name(dev, ie)) { wpabuf_free(ie); return NULL; } #endif /* CONFIG_WPS2 */ return wps_ie_encapsulate(ie); }
/** * wps_build_probe_req_ie - Build WPS IE for Probe Request * @pbc: Whether searching for PBC mode APs * @dev: Device attributes * @uuid: Own UUID * @req_type: Value for Request Type attribute * Returns: WPS IE or %NULL on failure * * The caller is responsible for freeing the buffer. */ struct wpabuf * wps_build_probe_req_ie(int pbc, struct wps_device_data *dev, const u8 *uuid, enum wps_request_type req_type) { struct wpabuf *ie; u8 *len; u16 methods; wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for Probe Request"); ie = wpabuf_alloc(200); if (ie == NULL) return NULL; wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC); len = wpabuf_put(ie, 1); wpabuf_put_be32(ie, WPS_DEV_OUI_WFA); if (pbc) methods = WPS_CONFIG_PUSHBUTTON; else { methods = WPS_CONFIG_LABEL | WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD; #ifdef CONFIG_WPS_UFD methods |= WPS_CONFIG_USBA; #endif /* CONFIG_WPS_UFD */ #ifdef CONFIG_WPS_NFC methods |= WPS_CONFIG_NFC_INTERFACE; #endif /* CONFIG_WPS_NFC */ } if (wps_build_version(ie) || wps_build_req_type(ie, req_type) || wps_build_config_methods(ie, methods) || wps_build_uuid_e(ie, uuid) || wps_build_primary_dev_type(dev, ie) || wps_build_rf_bands(dev, ie) || wps_build_assoc_state(NULL, ie) || wps_build_config_error(ie, WPS_CFG_NO_ERROR) || wps_build_dev_password_id(ie, pbc ? DEV_PW_PUSHBUTTON : DEV_PW_DEFAULT)) { wpabuf_free(ie); return NULL; } *len = wpabuf_len(ie) - 2; return ie; }
static struct wpabuf * wps_build_m7(struct wps_data *wps) { struct wpabuf *msg, *plain; wpa_printf(MSG_DEBUG, "WPS: Building Message M7"); plain = wpabuf_alloc(500 + wps->wps->ap_settings_len); if (plain == NULL) return NULL; msg = wpabuf_alloc(1000 + wps->wps->ap_settings_len); if (msg == NULL) { wpabuf_free(plain); return NULL; } if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_M7) || wps_build_registrar_nonce(wps, msg) || wps_build_e_snonce2(wps, plain) || (wps->wps->ap && wps_build_ap_settings(wps, plain)) || wps_build_key_wrap_auth(wps, plain) || wps_build_encr_settings(wps, msg, plain) || wps_build_wfa_ext(msg, 0, NULL, 0) || wps_build_authenticator(wps, msg)) { wpabuf_free(plain); wpabuf_free(msg); return NULL; } wpabuf_free(plain); if (wps->wps->ap && wps->wps->registrar) { /* * If the Registrar is only learning our current configuration, * it may not continue protocol run to successful completion. * Store information here to make sure it remains available. */ wps_device_store(wps->wps->registrar, &wps->peer_dev, wps->uuid_r); } wps->state = RECV_M8; return msg; }
static struct wpabuf * wps_build_m1(struct wps_data *wps) { struct wpabuf *msg; u16 methods; if (os_get_random(wps->nonce_e, WPS_NONCE_LEN) < 0) return NULL; wpa_hexdump(MSG_DEBUG, "WPS: Enrollee Nonce", wps->nonce_e, WPS_NONCE_LEN); wpa_printf(MSG_DEBUG, "WPS: Building Message M1"); msg = wpabuf_alloc(1000); if (msg == NULL) return NULL; methods = WPS_CONFIG_LABEL | WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD; if (wps->pbc) methods |= WPS_CONFIG_PUSHBUTTON; if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_M1) || wps_build_uuid_e(msg, wps->uuid_e) || wps_build_mac_addr(wps, msg) || wps_build_enrollee_nonce(wps, msg) || wps_build_public_key(wps, msg) || wps_build_auth_type_flags(wps, msg) || wps_build_encr_type_flags(wps, msg) || wps_build_conn_type_flags(wps, msg) || wps_build_config_methods(msg, methods) || wps_build_wps_state(wps, msg) || wps_build_device_attrs(&wps->wps->dev, msg) || wps_build_rf_bands(&wps->wps->dev, msg) || wps_build_assoc_state(wps, msg) || wps_build_dev_password_id(msg, wps->dev_pw_id) || wps_build_config_error(msg, WPS_CFG_NO_ERROR) || wps_build_os_version(&wps->wps->dev, msg)) { wpabuf_free(msg); return NULL; } wps->state = RECV_M2; return msg; }
/** * wps_build_probe_req_ie - Build WPS IE for Probe Request * @pw_id: Password ID (DEV_PW_PUSHBUTTON for active PBC and DEV_PW_DEFAULT for * most other use cases) * @dev: Device attributes * @uuid: Own UUID * @req_type: Value for Request Type attribute * @num_req_dev_types: Number of requested device types * @req_dev_types: Requested device types (8 * num_req_dev_types octets) or * %NULL if none * Returns: WPS IE or %NULL on failure * * The caller is responsible for freeing the buffer. */ struct wpabuf *wps_build_probe_req_ie(u16 pw_id, struct wps_device_data *dev, const u8 *uuid, enum wps_request_type req_type, unsigned int num_req_dev_types, const u8 *req_dev_types) { struct wpabuf *ie; wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for Probe Request"); ie = wpabuf_alloc(500); if (ie == NULL) { return NULL; } if (wps_build_version(ie) || wps_build_req_type(ie, req_type) || wps_build_config_methods(ie, dev->config_methods) || wps_build_uuid_e(ie, uuid) || wps_build_primary_dev_type(dev, ie) || wps_build_rf_bands(dev, ie, 0) || wps_build_assoc_state(NULL, ie) || wps_build_config_error(ie, WPS_CFG_NO_ERROR) || wps_build_dev_password_id(ie, pw_id) || wps_build_manufacturer(dev, ie) || wps_build_model_name(dev, ie) || wps_build_model_number(dev, ie) || wps_build_dev_name(dev, ie) || wps_build_wfa_ext(ie, req_type == WPS_REQ_ENROLLEE, NULL, 0) || wps_build_req_dev_type(dev, ie, num_req_dev_types, req_dev_types) || wps_build_secondary_dev_type(dev, ie) ) { wpabuf_free(ie); return NULL; } return wps_ie_encapsulate(ie); }
static struct wpabuf * wps_build_wsc_ack(struct wps_data *wps) { struct wpabuf *msg; wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_ACK"); msg = wpabuf_alloc(1000); if (msg == NULL) return NULL; if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_WSC_ACK) || wps_build_enrollee_nonce(wps, msg) || wps_build_registrar_nonce(wps, msg)) { wpabuf_free(msg); return NULL; } return msg; }
static struct wpabuf * build_fake_wsc_ack(void) { struct wpabuf *msg = wpabuf_alloc(100); if (msg == NULL) return NULL; wpabuf_put_u8(msg, UPNP_WPS_WLANEVENT_TYPE_EAP); wpabuf_put_str(msg, "00:00:00:00:00:00"); if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_WSC_ACK)) { wpabuf_free(msg); return NULL; } /* Enrollee Nonce */ wpabuf_put_be16(msg, ATTR_ENROLLEE_NONCE); wpabuf_put_be16(msg, WPS_NONCE_LEN); wpabuf_put(msg, WPS_NONCE_LEN); /* Registrar Nonce */ wpabuf_put_be16(msg, ATTR_REGISTRAR_NONCE); wpabuf_put_be16(msg, WPS_NONCE_LEN); wpabuf_put(msg, WPS_NONCE_LEN); return msg; }
struct wpabuf * wps_build_wsc_nack(struct wps_data *wps) { struct wpabuf *msg; wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_NACK"); msg = wpabuf_alloc(1000); if (msg == NULL) return NULL; if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_WSC_NACK) || wps_build_enrollee_nonce(wps, msg) || wps_build_registrar_nonce(wps, msg) || wps_build_config_error(msg, wps->config_error) || wps_build_wfa_ext(msg, 0, NULL, 0)) { wpabuf_free(msg); return NULL; } return msg; }
struct wpabuf * wps_er_config_token_from_cred(struct wps_context *wps, struct wps_credential *cred) { struct wpabuf *ret; struct wps_data data; ret = wpabuf_alloc(500); if (ret == NULL) return NULL; os_memset(&data, 0, sizeof(data)); data.wps = wps; data.use_cred = cred; if (wps_build_version(ret) || wps_build_cred(&data, ret) || wps_build_wfa_ext(ret, 0, NULL, 0)) { wpabuf_free(ret); return NULL; } return ret; }
struct wpabuf * wps_build_nfc_pw_token(u16 dev_pw_id, const struct wpabuf *pubkey, const struct wpabuf *dev_pw) { struct wpabuf *data; data = wpabuf_alloc(200); if (data == NULL) return NULL; if (wps_build_version(data) || wps_build_oob_dev_pw(data, dev_pw_id, pubkey, wpabuf_head(dev_pw), wpabuf_len(dev_pw)) || wps_build_wfa_ext(data, 0, NULL, 0)) { wpa_printf(MSG_ERROR, "WPS: Failed to build NFC password " "token"); wpabuf_free(data); return NULL; } return data; }
static struct wpabuf * wps_build_m3(struct wps_data *wps) { struct wpabuf *msg; wpa_printf(MSG_DEBUG, "WPS: Building Message M3"); if (wps->dev_password == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Device Password available"); return NULL; } if (wps_derive_psk(wps, wps->dev_password, wps->dev_password_len) < 0) return NULL; if (wps->wps->ap && random_pool_ready() != 1) { wpa_printf(MSG_INFO, "WPS: Not enough entropy in random pool to proceed - do not allow AP PIN to be used"); return NULL; } msg = wpabuf_alloc(1000); if (msg == NULL) return NULL; if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_M3) || wps_build_registrar_nonce(wps, msg) || wps_build_e_hash(wps, msg) || wps_build_wfa_ext(msg, 0, NULL, 0) || wps_build_authenticator(wps, msg)) { wpabuf_free(msg); return NULL; } wps->state = RECV_M4; return msg; }
void p2p_build_wps_ie(struct p2p_data *p2p, struct wpabuf *buf, u16 pw_id, int all_attr) { u8 *len; int i; wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC); len = wpabuf_put(buf, 1); wpabuf_put_be32(buf, WPS_DEV_OUI_WFA); wps_build_version(buf); if (all_attr) { wpabuf_put_be16(buf, ATTR_WPS_STATE); wpabuf_put_be16(buf, 1); wpabuf_put_u8(buf, WPS_STATE_NOT_CONFIGURED); } /* Device Password ID */ wpabuf_put_be16(buf, ATTR_DEV_PASSWORD_ID); wpabuf_put_be16(buf, 2); wpa_printf(MSG_DEBUG, "P2P: WPS IE Device Password ID: %d", pw_id); wpabuf_put_be16(buf, pw_id); if (all_attr) { size_t nlen; wpabuf_put_be16(buf, ATTR_RESPONSE_TYPE); wpabuf_put_be16(buf, 1); wpabuf_put_u8(buf, WPS_RESP_ENROLLEE_INFO); #if 0 /* FIX */ wps_build_uuid_e(buf, reg->wps->uuid); wps_build_manufacturer(dev, buf); wps_build_model_name(dev, buf); wps_build_model_number(dev, buf); wps_build_serial_number(dev, buf); #endif wpabuf_put_be16(buf, ATTR_PRIMARY_DEV_TYPE); wpabuf_put_be16(buf, WPS_DEV_TYPE_LEN); wpabuf_put_data(buf, p2p->cfg->pri_dev_type, WPS_DEV_TYPE_LEN); wpabuf_put_be16(buf, ATTR_DEV_NAME); nlen = p2p->cfg->dev_name ? os_strlen(p2p->cfg->dev_name) : 0; wpabuf_put_be16(buf, nlen); if (p2p->cfg->dev_name) wpabuf_put_data(buf, p2p->cfg->dev_name, nlen); wpabuf_put_be16(buf, ATTR_CONFIG_METHODS); wpabuf_put_be16(buf, 2); wpabuf_put_be16(buf, 0); /* FIX: ? */ } wps_build_wfa_ext(buf, 0, NULL, 0); if (all_attr && p2p->cfg->num_sec_dev_types) { wpabuf_put_be16(buf, ATTR_SECONDARY_DEV_TYPE_LIST); wpabuf_put_be16(buf, WPS_DEV_TYPE_LEN * p2p->cfg->num_sec_dev_types); wpabuf_put_data(buf, p2p->cfg->sec_dev_type, WPS_DEV_TYPE_LEN * p2p->cfg->num_sec_dev_types); } /* Add the WPS vendor extensions */ for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) { if (p2p->wps_vendor_ext[i] == NULL) break; if (wpabuf_tailroom(buf) < 4 + wpabuf_len(p2p->wps_vendor_ext[i])) continue; wpabuf_put_be16(buf, ATTR_VENDOR_EXT); wpabuf_put_be16(buf, wpabuf_len(p2p->wps_vendor_ext[i])); wpabuf_put_buf(buf, p2p->wps_vendor_ext[i]); } p2p_buf_update_ie_hdr(buf, len); }
int p2p_build_wps_ie(struct p2p_data *p2p, struct wpabuf *buf, int pw_id, int all_attr) { u8 *len; int i; if (wpabuf_tailroom(buf) < 6) return -1; wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC); len = wpabuf_put(buf, 1); wpabuf_put_be32(buf, WPS_DEV_OUI_WFA); if (wps_build_version(buf) < 0) return -1; if (all_attr) { if (wpabuf_tailroom(buf) < 5) return -1; wpabuf_put_be16(buf, ATTR_WPS_STATE); wpabuf_put_be16(buf, 1); wpabuf_put_u8(buf, WPS_STATE_NOT_CONFIGURED); } if (pw_id >= 0) { if (wpabuf_tailroom(buf) < 6) return -1; /* Device Password ID */ wpabuf_put_be16(buf, ATTR_DEV_PASSWORD_ID); wpabuf_put_be16(buf, 2); wpa_printf(MSG_DEBUG, "P2P: WPS IE Device Password ID: %d", pw_id); wpabuf_put_be16(buf, pw_id); } if (all_attr) { if (wpabuf_tailroom(buf) < 5) return -1; wpabuf_put_be16(buf, ATTR_RESPONSE_TYPE); wpabuf_put_be16(buf, 1); wpabuf_put_u8(buf, WPS_RESP_ENROLLEE_INFO); if (wps_build_uuid_e(buf, p2p->cfg->uuid) < 0 || p2p_add_wps_string(buf, ATTR_MANUFACTURER, p2p->cfg->manufacturer) < 0 || p2p_add_wps_string(buf, ATTR_MODEL_NAME, p2p->cfg->model_name) < 0 || p2p_add_wps_string(buf, ATTR_MODEL_NUMBER, p2p->cfg->model_number) < 0 || p2p_add_wps_string(buf, ATTR_SERIAL_NUMBER, p2p->cfg->serial_number) < 0) return -1; if (wpabuf_tailroom(buf) < 4 + WPS_DEV_TYPE_LEN) return -1; wpabuf_put_be16(buf, ATTR_PRIMARY_DEV_TYPE); wpabuf_put_be16(buf, WPS_DEV_TYPE_LEN); wpabuf_put_data(buf, p2p->cfg->pri_dev_type, WPS_DEV_TYPE_LEN); if (p2p_add_wps_string(buf, ATTR_DEV_NAME, p2p->cfg->dev_name) < 0) return -1; if (wpabuf_tailroom(buf) < 6) return -1; wpabuf_put_be16(buf, ATTR_CONFIG_METHODS); wpabuf_put_be16(buf, 2); wpabuf_put_be16(buf, p2p->cfg->config_methods); } if (wps_build_wfa_ext(buf, 0, NULL, 0) < 0) return -1; if (all_attr && p2p->cfg->num_sec_dev_types) { if (wpabuf_tailroom(buf) < 4 + WPS_DEV_TYPE_LEN * p2p->cfg->num_sec_dev_types) return -1; wpabuf_put_be16(buf, ATTR_SECONDARY_DEV_TYPE_LIST); wpabuf_put_be16(buf, WPS_DEV_TYPE_LEN * p2p->cfg->num_sec_dev_types); wpabuf_put_data(buf, p2p->cfg->sec_dev_type, WPS_DEV_TYPE_LEN * p2p->cfg->num_sec_dev_types); } /* Add the WPS vendor extensions */ for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) { if (p2p->wps_vendor_ext[i] == NULL) break; if (wpabuf_tailroom(buf) < 4 + wpabuf_len(p2p->wps_vendor_ext[i])) continue; wpabuf_put_be16(buf, ATTR_VENDOR_EXT); wpabuf_put_be16(buf, wpabuf_len(p2p->wps_vendor_ext[i])); wpabuf_put_buf(buf, p2p->wps_vendor_ext[i]); } p2p_buf_update_ie_hdr(buf, len); return 0; }
/** * wps_build_probe_req_ie - Build WPS IE for Probe Request * @pbc: Whether searching for PBC mode APs * @dev: Device attributes * @uuid: Own UUID * @req_type: Value for Request Type attribute * @num_req_dev_types: Number of requested device types * @req_dev_types: Requested device types (8 * num_req_dev_types octets) or * %NULL if none * Returns: WPS IE or %NULL on failure * * The caller is responsible for freeing the buffer. */ struct wpabuf * wps_build_probe_req_ie(int pbc, struct wps_device_data *dev, const u8 *uuid, enum wps_request_type req_type, unsigned int num_req_dev_types, const u8 *req_dev_types) { struct wpabuf *ie; u16 methods = 0; wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for Probe Request"); ie = wpabuf_alloc(500); if (ie == NULL) return NULL; methods |= WPS_CONFIG_PUSHBUTTON; #ifdef CONFIG_WPS2 /* * TODO: Should figure out whether this device has a physical or * virtual pushbutton. */ methods |= WPS_CONFIG_VIRT_PUSHBUTTON; #endif /* CONFIG_WPS2 */ /* * TODO: Should figure out whether this Probe Request was triggered * using physical or virtual display. Also, if the device has a PIN on * a label, that should be indicated here. */ methods |= WPS_CONFIG_DISPLAY | #ifdef CONFIG_WPS2 WPS_CONFIG_VIRT_DISPLAY | #endif /* CONFIG_WPS2 */ WPS_CONFIG_KEYPAD; #ifdef CONFIG_WPS_UFD methods |= WPS_CONFIG_USBA; #endif /* CONFIG_WPS_UFD */ #ifdef CONFIG_WPS_NFC methods |= WPS_CONFIG_NFC_INTERFACE; #endif /* CONFIG_WPS_NFC */ if (wps_build_version(ie) || wps_build_req_type(ie, req_type) || wps_build_config_methods(ie, methods) || wps_build_uuid_e(ie, uuid) || wps_build_primary_dev_type(dev, ie) || wps_build_rf_bands(dev, ie) || wps_build_assoc_state(NULL, ie) || wps_build_config_error(ie, WPS_CFG_NO_ERROR) || wps_build_dev_password_id(ie, pbc ? DEV_PW_PUSHBUTTON : DEV_PW_DEFAULT) || #ifdef CONFIG_WPS2 wps_build_manufacturer(dev, ie) || wps_build_model_name(dev, ie) || wps_build_model_number(dev, ie) || wps_build_dev_name(dev, ie) || wps_build_wfa_ext(ie, req_type == WPS_REQ_ENROLLEE, NULL, 0) || #endif /* CONFIG_WPS2 */ wps_build_req_dev_type(dev, ie, num_req_dev_types, req_dev_types) || wps_build_secondary_dev_type(dev, ie) ) { wpabuf_free(ie); return NULL; } #ifndef CONFIG_WPS2 if (dev->p2p && wps_build_dev_name(dev, ie)) { wpabuf_free(ie); return NULL; } #endif /* CONFIG_WPS2 */ return wps_ie_encapsulate(ie); }