Ejemplo n.º 1
0
/**
 * wpabuf_concat - Concatenate two buffers into a newly allocated one
 * @a: First buffer
 * @b: Second buffer
 * Returns: wpabuf with concatenated a + b data or %NULL on failure
 *
 * Both buffers a and b will be freed regardless of the return value. Input
 * buffers can be %NULL which is interpreted as an empty buffer.
 */
struct wpabuf * wpabuf_concat(struct wpabuf *a, struct wpabuf *b)
{
    struct wpabuf *n = NULL;
    size_t len = 0;

    if (b == NULL)
        return a;

    if (a)
        len += wpabuf_len(a);
    if (b)
        len += wpabuf_len(b);

    n = wpabuf_alloc(len);
    if (n) {
        if (a)
            wpabuf_put_buf(n, a);
        if (b)
            wpabuf_put_buf(n, b);
    }

    wpabuf_free(a);
    wpabuf_free(b);

    return n;
}
Ejemplo n.º 2
0
static struct wpabuf * p2p_build_prov_disc_resp(struct p2p_data *p2p,
        u8 dialog_token,
        u16 config_methods,
        const u8 *group_id,
        size_t group_id_len)
{
    struct wpabuf *buf;
    size_t extra = 0;

#ifdef CONFIG_WIFI_DISPLAY
    struct wpabuf *wfd_ie = p2p->wfd_ie_prov_disc_resp;
    if (wfd_ie && group_id) {
        size_t i;
        for (i = 0; i < p2p->num_groups; i++) {
            struct p2p_group *g = p2p->groups[i];
            struct wpabuf *ie;
            if (!p2p_group_is_group_id_match(g, group_id,
                                             group_id_len))
                continue;
            ie = p2p_group_get_wfd_ie(g);
            if (ie) {
                wfd_ie = ie;
                break;
            }
        }
    }
    if (wfd_ie)
        extra = wpabuf_len(wfd_ie);
#endif /* CONFIG_WIFI_DISPLAY */

    if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_PD_RESP])
        extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_P2P_PD_RESP]);

    buf = wpabuf_alloc(100 + extra);
    if (buf == NULL)
        return NULL;

    p2p_buf_add_public_action_hdr(buf, P2P_PROV_DISC_RESP, dialog_token);

    /* WPS IE with Config Methods attribute */
    p2p_build_wps_ie_config_methods(buf, config_methods);

#ifdef CONFIG_WIFI_DISPLAY
    if (wfd_ie)
        wpabuf_put_buf(buf, wfd_ie);
#endif /* CONFIG_WIFI_DISPLAY */

    if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_PD_RESP])
        wpabuf_put_buf(buf, p2p->vendor_elem[VENDOR_ELEM_P2P_PD_RESP]);

    return buf;
}
Ejemplo n.º 3
0
static struct wpabuf *
wifi_display_build_go_ie(struct p2p_group *group)
{
	struct wpabuf *wfd_subelems, *wfd_ie;
	struct p2p_group_member *m;
	u8 *len;
	unsigned int count = 0;

	if (!group->p2p->wfd_ie_probe_resp)
		return NULL;

	wfd_subelems = wpabuf_alloc(wpabuf_len(group->p2p->wfd_ie_probe_resp) +
				    group->num_members * 24 + 100);
	if (wfd_subelems == NULL)
		return NULL;
	if (group->p2p->wfd_dev_info)
		wpabuf_put_buf(wfd_subelems, group->p2p->wfd_dev_info);
	if (group->p2p->wfd_assoc_bssid)
		wpabuf_put_buf(wfd_subelems,
			       group->p2p->wfd_assoc_bssid);
	if (group->p2p->wfd_coupled_sink_info)
		wpabuf_put_buf(wfd_subelems,
			       group->p2p->wfd_coupled_sink_info);

	/* Build WFD Session Info */
	wpabuf_put_u8(wfd_subelems, WFD_SUBELEM_SESSION_INFO);
	len = wpabuf_put(wfd_subelems, 2);
	m = group->members;
	while (m) {
		if (wifi_display_add_dev_info_descr(wfd_subelems, m))
			count++;
		m = m->next;
	}

	if (count == 0) {
		/* No Wi-Fi Display clients - do not include subelement */
		wfd_subelems->used -= 3;
	} else {
		WPA_PUT_BE16(len, (u8 *) wpabuf_put(wfd_subelems, 0) - len -
			     2);
		wpa_printf(MSG_DEBUG, "WFD: WFD Session Info: %u descriptors",
			   count);
	}

	wfd_ie = wifi_display_encaps(wfd_subelems);
	wpabuf_free(wfd_subelems);

	return wfd_ie;
}
Ejemplo n.º 4
0
int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg)
{
	struct wpabuf *pubkey;

	wpa_printf(MSG_DEBUG, "WPS:  * Public Key");
	pubkey = dh_init(dh_groups_get(WPS_DH_GROUP), &wps->dh_privkey);
	pubkey = wpabuf_zeropad(pubkey, 192);
	if (pubkey == NULL) {
		wpa_printf(MSG_DEBUG, "WPS: Failed to initialize "
			   "Diffie-Hellman handshake");
		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;
}
static struct wpabuf * p2p_build_sd_response(u8 dialog_token, u16 status_code,
					     u16 comeback_delay,
					     u16 update_indic,
					     const struct wpabuf *tlvs)
{
	struct wpabuf *buf;
	u8 *len_pos;

	buf = gas_anqp_build_initial_resp(dialog_token, status_code,
					  comeback_delay,
					  100 + (tlvs ? wpabuf_len(tlvs) : 0));
	if (buf == NULL)
		return NULL;

	if (tlvs) {
		/* ANQP Query Response Frame */
		len_pos = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
		wpabuf_put_be32(buf, P2P_IE_VENDOR_TYPE);
		 /* Service Update Indicator */
		wpabuf_put_le16(buf, update_indic);
		wpabuf_put_buf(buf, tlvs);
		gas_anqp_set_element_len(buf, len_pos);
	}

	gas_anqp_set_len(buf);

	return buf;
}
static int eap_fast_encrypt_phase2(struct eap_sm *sm,
				   struct eap_fast_data *data,
				   struct wpabuf *plain, int piggyback)
{
	struct wpabuf *encr;

	wpa_hexdump_buf_key(MSG_DEBUG, "EAP-FAST: Encrypting Phase 2 TLVs",
			    plain);
	encr = eap_server_tls_encrypt(sm, &data->ssl, plain);
	wpabuf_free(plain);

	if (data->ssl.tls_out && piggyback) {
		wpa_printf(MSG_DEBUG, "EAP-FAST: Piggyback Phase 2 data "
			   "(len=%d) with last Phase 1 Message (len=%d "
			   "used=%d)",
			   (int) wpabuf_len(encr),
			   (int) wpabuf_len(data->ssl.tls_out),
			   (int) data->ssl.tls_out_pos);
		if (wpabuf_resize(&data->ssl.tls_out, wpabuf_len(encr)) < 0) {
			wpa_printf(MSG_WARNING, "EAP-FAST: Failed to resize "
				   "output buffer");
			wpabuf_free(encr);
			return -1;
		}
		wpabuf_put_buf(data->ssl.tls_out, encr);
		wpabuf_free(encr);
	} else {
		wpabuf_free(data->ssl.tls_out);
		data->ssl.tls_out_pos = 0;
		data->ssl.tls_out = encr;
	}

	return 0;
}
Ejemplo n.º 7
0
static int ikev2_build_ker(struct ikev2_responder_data *data,
			   struct wpabuf *msg, u8 next_payload)
{
	struct ikev2_payload_hdr *phdr;
	size_t plen;
	struct wpabuf *pv;

	wpa_printf(MSG_DEBUG, "IKEV2: Adding KEr payload");

	pv = dh_init(data->dh, &data->r_dh_private);
	if (pv == NULL) {
		wpa_printf(MSG_DEBUG, "IKEV2: Failed to initialize DH");
		return -1;
	}

	/* KEr - RFC 4306, Sect. 3.4 */
	phdr = wpabuf_put(msg, sizeof(*phdr));
	phdr->next_payload = next_payload;
	phdr->flags = 0;

	wpabuf_put_be16(msg, data->proposal.dh); /* DH Group # */
	wpabuf_put(msg, 2); /* RESERVED */
	/*
	 * RFC 4306, Sect. 3.4: possible zero padding for public value to
	 * match the length of the prime.
	 */
	wpabuf_put(msg, data->dh->prime_len - wpabuf_len(pv));
	wpabuf_put_buf(msg, pv);
	wpabuf_free(pv);

	plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr;
	WPA_PUT_BE16(phdr->payload_length, plen);
	return 0;
}
Ejemplo n.º 8
0
static struct wpabuf * eap_peap_build_phase2_soh(struct eap_sm *sm,
						 struct eap_peap_data *data,
						 u8 id)
{
	struct wpabuf *buf1, *buf, *encr_req;
	const u8 *req;
	size_t req_len;

	buf1 = tncs_build_soh_request();
	if (buf1 == NULL)
		return NULL;

	buf = eap_msg_alloc(EAP_VENDOR_MICROSOFT, 0x21, wpabuf_len(buf1),
			    EAP_CODE_REQUEST, id);
	if (buf == NULL) {
		wpabuf_free(buf1);
		return NULL;
	}
	wpabuf_put_buf(buf, buf1);
	wpabuf_free(buf1);

	req = wpabuf_head(buf);
	req_len = wpabuf_len(buf);

	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 SOH data",
			req, req_len);

	req += sizeof(struct eap_hdr);
	req_len -= sizeof(struct eap_hdr);

	encr_req = eap_server_tls_encrypt(sm, &data->ssl, req, req_len);
	wpabuf_free(buf);

	return encr_req;
}
Ejemplo n.º 9
0
static struct wpabuf * event_build_message(struct wps_event_ *e)
{
	struct wpabuf *buf;
	char *b;

	buf = wpabuf_alloc(1000 + wpabuf_len(e->data));
	if (buf == NULL)
		return NULL;
	wpabuf_printf(buf, "NOTIFY %s HTTP/1.1\r\n", e->addr->path);
	wpabuf_put_str(buf, "SERVER: Unspecified, UPnP/1.0, Unspecified\r\n");
	wpabuf_printf(buf, "HOST: %s\r\n", e->addr->domain_and_port);
	wpabuf_put_str(buf, "CONTENT-TYPE: text/xml; charset=\"utf-8\"\r\n"
		       "NT: upnp:event\r\n"
		       "NTS: upnp:propchange\r\n");
	wpabuf_put_str(buf, "SID: uuid:");
	b = wpabuf_put(buf, 0);
	uuid_bin2str(e->s->uuid, b, 80);
	wpabuf_put(buf, os_strlen(b));
	wpabuf_put_str(buf, "\r\n");
	wpabuf_printf(buf, "SEQ: %u\r\n", e->subscriber_sequence);
	wpabuf_printf(buf, "CONTENT-LENGTH: %d\r\n",
		      (int) wpabuf_len(e->data));
	wpabuf_put_str(buf, "\r\n"); /* terminating empty line */
	wpabuf_put_buf(buf, e->data);
	return buf;
}
Ejemplo n.º 10
0
struct wpabuf * wifi_display_get_wfd_ie(struct wpa_global *global)
{
	struct wpabuf *ie;
	size_t len;
	int i;

	if (global->p2p == NULL)
		return NULL;

	len = 0;
	for (i = 0; i < MAX_WFD_SUBELEMS; i++) {
		if (global->wfd_subelem[i])
			len += wpabuf_len(global->wfd_subelem[i]);
	}

	ie = wpabuf_alloc(len);
	if (ie == NULL)
		return NULL;

	for (i = 0; i < MAX_WFD_SUBELEMS; i++) {
		if (global->wfd_subelem[i])
			wpabuf_put_buf(ie, global->wfd_subelem[i]);
	}

	return ie;
}
Ejemplo n.º 11
0
int hs20_send_wnm_notification_deauth_req(struct hostapd_data *hapd,
					  const u8 *addr,
					  const struct wpabuf *payload)
{
	struct wpabuf *buf;
	int ret;

	/* TODO: should refuse to send notification if the STA is not associated
	 * or if the STA did not indicate support for WNM-Notification */

	buf = wpabuf_alloc(4 + 6 + wpabuf_len(payload));
	if (buf == NULL)
		return -1;

	wpabuf_put_u8(buf, WLAN_ACTION_WNM);
	wpabuf_put_u8(buf, WNM_NOTIFICATION_REQ);
	wpabuf_put_u8(buf, 1); /* Dialog token */
	wpabuf_put_u8(buf, 1); /* Type - 1 reserved for WFA */

	/* Deauthentication Imminent Notice subelement */
	wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
	wpabuf_put_u8(buf, 4 + wpabuf_len(payload));
	wpabuf_put_be24(buf, OUI_WFA);
	wpabuf_put_u8(buf, HS20_WNM_DEAUTH_IMMINENT_NOTICE);
	wpabuf_put_buf(buf, payload);

	ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
				      wpabuf_head(buf), wpabuf_len(buf));

	wpabuf_free(buf);

	return ret;
}
Ejemplo n.º 12
0
struct wpabuf * p2p_group_assoc_resp_ie(struct p2p_group *group, u8 status)
{
	struct wpabuf *resp;
	u8 *rlen;
	size_t extra = 0;

#ifdef CONFIG_WIFI_DISPLAY
	if (group->wfd_ie)
		extra = wpabuf_len(group->wfd_ie);
#endif /* CONFIG_WIFI_DISPLAY */

	/*
	 * (Re)Association Response - P2P IE
	 * Status attribute (shall be present when association request is
	 *	denied)
	 * Extended Listen Timing (may be present)
	 */
	resp = wpabuf_alloc(20 + extra);
	if (resp == NULL)
		return NULL;

#ifdef CONFIG_WIFI_DISPLAY
	if (group->wfd_ie)
		wpabuf_put_buf(resp, group->wfd_ie);
#endif /* CONFIG_WIFI_DISPLAY */

	rlen = p2p_buf_add_ie_hdr(resp);
	if (status != P2P_SC_SUCCESS)
		p2p_buf_add_status(resp, status);
	p2p_buf_update_ie_hdr(resp, rlen);

	return resp;
}
int wps_build_encr_settings(struct wps_data *wps, struct wpabuf *msg,
			    struct wpabuf *plain)
{
	size_t pad_len;
	const size_t block_size = 16;
	u8 *iv, *data;

	wpa_printf(MSG_DEBUG, "WPS:  * Encrypted Settings");

	/* PKCS#5 v2.0 pad */
	pad_len = block_size - wpabuf_len(plain) % block_size;
	os_memset(wpabuf_put(plain, pad_len), pad_len, pad_len);

	wpabuf_put_be16(msg, ATTR_ENCR_SETTINGS);
	wpabuf_put_be16(msg, block_size + wpabuf_len(plain));

	iv = wpabuf_put(msg, block_size);
	if (random_get_bytes(iv, block_size) < 0)
		return -1;

	data = wpabuf_put(msg, 0);
	wpabuf_put_buf(msg, plain);
	if (aes_128_cbc_encrypt(wps->keywrapkey, iv, data, wpabuf_len(plain)))
		return -1;

	return 0;
}
Ejemplo n.º 14
0
static struct wpabuf * p2p_group_build_beacon_ie(struct p2p_group *group)
{
	struct wpabuf *ie;
	u8 *len;
	size_t extra = 0;

#ifdef CONFIG_WIFI_DISPLAY
	if (group->p2p->wfd_ie_beacon)
		extra = wpabuf_len(group->p2p->wfd_ie_beacon);
#endif /* CONFIG_WIFI_DISPLAY */

	ie = wpabuf_alloc(257 + extra);
	if (ie == NULL)
		return NULL;

#ifdef CONFIG_WIFI_DISPLAY
	if (group->p2p->wfd_ie_beacon)
		wpabuf_put_buf(ie, group->p2p->wfd_ie_beacon);
#endif /* CONFIG_WIFI_DISPLAY */

	len = p2p_buf_add_ie_hdr(ie);
	p2p_group_add_common_ies(group, ie);
	p2p_buf_add_device_id(ie, group->p2p->cfg->dev_addr);
	p2p_group_add_noa(ie, group->noa);
	p2p_buf_update_ie_hdr(ie, len);

	return ie;
}
Ejemplo n.º 15
0
static struct wpabuf * eap_peapv2_tlv_eap_payload(struct wpabuf *buf)
{
	struct wpabuf *e;
	struct eap_tlv_hdr *tlv;

	if (buf == NULL)
		return NULL;

	/* Encapsulate EAP packet in EAP-Payload TLV */
	wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Add EAP-Payload TLV");
	e = wpabuf_alloc(sizeof(*tlv) + wpabuf_len(buf));
	if (e == NULL) {
		wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Failed to allocate memory "
			   "for TLV encapsulation");
		wpabuf_free(buf);
		return NULL;
	}
	tlv = wpabuf_put(e, sizeof(*tlv));
	tlv->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY |
				     EAP_TLV_EAP_PAYLOAD_TLV);
	tlv->length = host_to_be16(wpabuf_len(buf));
	wpabuf_put_buf(e, buf);
	wpabuf_free(buf);
	return e;
}
Ejemplo n.º 16
0
static struct wpabuf * p2p_build_prov_disc_req(struct p2p_data *p2p,
        u8 dialog_token,
        u16 config_methods,
        struct p2p_device *go)
{
    struct wpabuf *buf;
    u8 *len;
    size_t extra = 0;

#ifdef CONFIG_WIFI_DISPLAY
    if (p2p->wfd_ie_prov_disc_req)
        extra = wpabuf_len(p2p->wfd_ie_prov_disc_req);
#endif /* CONFIG_WIFI_DISPLAY */

    if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_PD_REQ])
        extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_P2P_PD_REQ]);

    buf = wpabuf_alloc(1000 + extra);
    if (buf == NULL)
        return NULL;

    p2p_buf_add_public_action_hdr(buf, P2P_PROV_DISC_REQ, dialog_token);

    len = p2p_buf_add_ie_hdr(buf);
    p2p_buf_add_capability(buf, p2p->dev_capab &
                           ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY, 0);
    p2p_buf_add_device_info(buf, p2p, NULL);
    if (go) {
        p2p_buf_add_group_id(buf, go->info.p2p_device_addr,
                             go->oper_ssid, go->oper_ssid_len);
    }
    p2p_buf_update_ie_hdr(buf, len);

    /* WPS IE with Config Methods attribute */
    p2p_build_wps_ie_config_methods(buf, config_methods);

#ifdef CONFIG_WIFI_DISPLAY
    if (p2p->wfd_ie_prov_disc_req)
        wpabuf_put_buf(buf, p2p->wfd_ie_prov_disc_req);
#endif /* CONFIG_WIFI_DISPLAY */

    if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_PD_REQ])
        wpabuf_put_buf(buf, p2p->vendor_elem[VENDOR_ELEM_P2P_PD_REQ]);

    return buf;
}
Ejemplo n.º 17
0
static void p2p_client_info(struct wpabuf *ie, struct p2p_group_member *m)
{
	if (m->client_info == NULL)
		return;
	if (wpabuf_tailroom(ie) < wpabuf_len(m->client_info) + 1)
		return;
	wpabuf_put_buf(ie, m->client_info);
}
static struct wpabuf * p2p_build_invitation_resp(struct p2p_data *p2p,
						 struct p2p_device *peer,
						 u8 dialog_token, u8 status,
						 const u8 *group_bssid,
						 u8 reg_class, u8 channel,
						 struct p2p_channels *channels)
{
	struct wpabuf *buf;
	u8 *len;
	size_t extra = 0;

#ifdef CONFIG_WIFI_DISPLAY
	struct wpabuf *wfd_ie = p2p->wfd_ie_invitation;
	if (wfd_ie && group_bssid) {
		size_t i;
		for (i = 0; i < p2p->num_groups; i++) {
			struct p2p_group *g = p2p->groups[i];
			struct wpabuf *ie;
			if (!p2p_group_is_group_id_match(g, group_bssid,
							 ETH_ALEN))
				continue;
			ie = p2p_group_get_wfd_ie(g);
			if (ie) {
				wfd_ie = ie;
				break;
			}
		}
	}
	if (wfd_ie)
		extra = wpabuf_len(wfd_ie);
#endif /* CONFIG_WIFI_DISPLAY */

	buf = wpabuf_alloc(1000 + extra);
	if (buf == NULL)
		return NULL;

	p2p_buf_add_public_action_hdr(buf, P2P_INVITATION_RESP,
				      dialog_token);

	len = p2p_buf_add_ie_hdr(buf);
	p2p_buf_add_status(buf, status);
	p2p_buf_add_config_timeout(buf, 0, 0); /* FIX */
	if (reg_class && channel)
		p2p_buf_add_operating_channel(buf, p2p->cfg->country,
					      reg_class, channel);
	if (group_bssid)
		p2p_buf_add_group_bssid(buf, group_bssid);
	if (channels)
		p2p_buf_add_channel_list(buf, p2p->cfg->country, channels);
	p2p_buf_update_ie_hdr(buf, len);

#ifdef CONFIG_WIFI_DISPLAY
	if (wfd_ie)
		wpabuf_put_buf(buf, wfd_ie);
#endif /* CONFIG_WIFI_DISPLAY */

	return buf;
}
Ejemplo n.º 19
0
static void p2p_group_add_noa(struct wpabuf *ie, struct wpabuf *noa)
{
	if (noa == NULL)
		return;
	/* Notice of Absence */
	wpabuf_put_u8(ie, P2P_ATTR_NOTICE_OF_ABSENCE);
	wpabuf_put_le16(ie, wpabuf_len(noa));
	wpabuf_put_buf(ie, noa);
}
Ejemplo n.º 20
0
static int add_buf(struct wpabuf **dst, const struct wpabuf *src)
{
	if (!src)
		return 0;
	if (wpabuf_resize(dst, wpabuf_len(src)) != 0)
		return -1;
	wpabuf_put_buf(*dst, src);
	return 0;
}
Ejemplo n.º 21
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;
}
Ejemplo n.º 22
0
/**
 * eap_peer_tls_reassemble_fragment - Reassemble a received fragment
 * @data: Data for TLS processing
 * @in_data: Next incoming TLS segment
 * Returns: 0 on success, 1 if more data is needed for the full message, or
 * -1 on error
 */
static int eap_peer_tls_reassemble_fragment(struct eap_ssl_data *data,
					    const struct wpabuf *in_data)
{
	size_t tls_in_len, in_len;

	tls_in_len = data->tls_in ? wpabuf_len(data->tls_in) : 0;
	in_len = in_data ? wpabuf_len(in_data) : 0;

	if (tls_in_len + in_len == 0) {
		/* No message data received?! */
		wpa_printf(MSG_WARNING, "SSL: Invalid reassembly state: "
			   "tls_in_left=%lu tls_in_len=%lu in_len=%lu",
			   (unsigned long) data->tls_in_left,
			   (unsigned long) tls_in_len,
			   (unsigned long) in_len);
		eap_peer_tls_reset_input(data);
		return -1;
	}

	if (tls_in_len + in_len > 65536) {
		/*
		 * Limit length to avoid rogue servers from causing large
		 * memory allocations.
		 */
		wpa_printf(MSG_INFO, "SSL: Too long TLS fragment (size over "
			   "64 kB)");
		eap_peer_tls_reset_input(data);
		return -1;
	}

	if (in_len > data->tls_in_left) {
		/* Sender is doing something odd - reject message */
		wpa_printf(MSG_INFO, "SSL: more data than TLS message length "
			   "indicated");
		eap_peer_tls_reset_input(data);
		return -1;
	}

	if (wpabuf_resize(&data->tls_in, in_len) < 0) {
		wpa_printf(MSG_INFO, "SSL: Could not allocate memory for TLS "
			   "data");
		eap_peer_tls_reset_input(data);
		return -1;
	}
	if (in_data)
		wpabuf_put_buf(data->tls_in, in_data);
	data->tls_in_left -= in_len;

	if (data->tls_in_left > 0) {
		wpa_printf(MSG_DEBUG, "SSL: Need %lu bytes more input "
			   "data", (unsigned long) data->tls_in_left);
		return 1;
	}

	return 0;
}
Ejemplo n.º 23
0
static int eap_peapv2_start_phase2(struct eap_sm *sm,
				   struct eap_peap_data *data)
{
	struct wpabuf *buf, *buf2;
	int res;

	wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Phase1 done, include first Phase2 "
		   "payload in the same message");
	eap_peap_state(data, PHASE1_ID2);
	if (eap_peap_phase2_init(sm, data, EAP_TYPE_IDENTITY))
		return -1;

	/* TODO: which Id to use here? */
	buf = data->phase2_method->buildReq(sm, data->phase2_priv, 6);
	if (buf == NULL)
		return -1;

	buf2 = eap_peapv2_tlv_eap_payload(buf);
	if (buf2 == NULL)
		return -1;

	wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAPv2: Identity Request", buf2);

	buf = wpabuf_alloc(data->ssl.tls_out_limit);
	if (buf == NULL) {
		wpabuf_free(buf2);
		return -1;
	}

	res = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn,
				     wpabuf_head(buf2), wpabuf_len(buf2),
				     wpabuf_put(buf, 0),
				     data->ssl.tls_out_limit);
	wpabuf_free(buf2);

	if (res < 0) {
		wpa_printf(MSG_INFO, "EAP-PEAPv2: Failed to encrypt Phase 2 "
			   "data");
		wpabuf_free(buf);
		return -1;
	}

	wpabuf_put(buf, res);
	wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAPv2: Encrypted Identity Request",
			buf);

	/* Append TLS data into the pending buffer after the Server Finished */
	if (wpabuf_resize(&data->ssl.out_buf, wpabuf_len(buf)) < 0) {
		wpabuf_free(buf);
		return -1;
	}
	wpabuf_put_buf(data->ssl.out_buf, buf);
	wpabuf_free(buf);

	return 0;
}
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;
}
Ejemplo n.º 25
0
static struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s)
{
	struct wpabuf *extra_ie = NULL;
#ifdef CONFIG_WPS
	int wps = 0;
	enum wps_request_type req_type = WPS_REQ_ENROLLEE_INFO;
#endif /* CONFIG_WPS */

#ifdef CONFIG_INTERWORKING
	if (wpa_s->conf->interworking &&
	    wpabuf_resize(&extra_ie, 100) == 0)
		wpas_add_interworking_elements(wpa_s, extra_ie);
#endif /* CONFIG_INTERWORKING */

#ifdef CONFIG_WPS
	wps = wpas_wps_in_use(wpa_s, &req_type);

	if (wps) {
		struct wpabuf *wps_ie;
		wps_ie = wps_build_probe_req_ie(wps == 2 ? DEV_PW_PUSHBUTTON :
						DEV_PW_DEFAULT,
						&wpa_s->wps->dev,
						wpa_s->wps->uuid, req_type,
						0, NULL);
		if (wps_ie) {
			if (wpabuf_resize(&extra_ie, wpabuf_len(wps_ie)) == 0)
				wpabuf_put_buf(extra_ie, wps_ie);
			wpabuf_free(wps_ie);
		}
	}

#ifdef CONFIG_P2P
	if (wps) {
		size_t ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p);
		if (wpabuf_resize(&extra_ie, ielen) == 0)
			wpas_p2p_scan_ie(wpa_s, extra_ie);
	}
#endif /* CONFIG_P2P */

#endif /* CONFIG_WPS */

#ifdef CONFIG_HS20
	if (wpa_s->conf->hs20 && wpabuf_resize(&extra_ie, 7) == 0)
		wpas_hs20_add_indication(extra_ie);
#endif /* CONFIG_HS20 */

	return extra_ie;
}
Ejemplo n.º 26
0
static struct wpabuf * ndef_build_record(u8 flags, void *type,
					 u8 type_length, void *id,
					 u8 id_length,
					 const struct wpabuf *payload)
{
	struct wpabuf *record;
	size_t total_len;
	int short_record;
	u8 local_flag;
	size_t payload_length = wpabuf_len(payload);

	short_record = payload_length < 256 ? 1 : 0;

	total_len = 2; /* flag + type length */
	/* payload length */
	total_len += short_record ? sizeof(u8) : sizeof(u32);
	if (id_length > 0)
		total_len += 1;
	total_len += type_length + id_length + payload_length;
	record = wpabuf_alloc(total_len);
	if (record == NULL) {
		wpa_printf(MSG_ERROR, "NDEF : Failed to allocate "
			   "record for build");
		return NULL;
	}

	local_flag = flags;
	if (id_length > 0)
		local_flag |= FLAG_ID_LENGTH_PRESENT;
	if (short_record)
		local_flag |= FLAG_SHORT_RECORD;
	wpabuf_put_u8(record, local_flag);

	wpabuf_put_u8(record, type_length);

	if (short_record)
		wpabuf_put_u8(record, payload_length);
	else
		wpabuf_put_be32(record, payload_length);

	if (id_length > 0)
		wpabuf_put_u8(record, id_length);
	wpabuf_put_data(record, type, type_length);
	wpabuf_put_data(record, id, id_length);
	wpabuf_put_buf(record, payload);
	return record;
}
Ejemplo n.º 27
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;
}
int wps_build_vendor_ext(struct wps_device_data *dev, struct wpabuf *msg)
{
	int i;

	for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
		if (dev->vendor_ext[i] == NULL)
			continue;
		wpa_hexdump(MSG_DEBUG, "WPS:  * Vendor Extension",
			    wpabuf_head_u8(dev->vendor_ext[i]),
			    wpabuf_len(dev->vendor_ext[i]));
		wpabuf_put_be16(msg, ATTR_VENDOR_EXT);
		wpabuf_put_be16(msg, wpabuf_len(dev->vendor_ext[i]));
		wpabuf_put_buf(msg, dev->vendor_ext[i]);
	}

	return 0;
}
Ejemplo n.º 29
0
static struct wpabuf * p2p_build_sd_response(u8 dialog_token, u16 status_code,
					     u16 comeback_delay,
					     u16 update_indic,
					     const struct wpabuf *tlvs)
{
	struct wpabuf *buf;
	u8 *len_pos, *len_pos2;

	buf = wpabuf_alloc(1000 + (tlvs ? wpabuf_len(tlvs) : 0));
	if (buf == NULL)
		return NULL;

	wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC);
	wpabuf_put_u8(buf, WLAN_PA_GAS_INITIAL_RESP);
	wpabuf_put_u8(buf, dialog_token);
	wpabuf_put_le16(buf, status_code);
	wpabuf_put_le16(buf, comeback_delay);

	/* Advertisement Protocol IE */
	wpabuf_put_u8(buf, WLAN_EID_ADV_PROTO);
	wpabuf_put_u8(buf, 2); /* Length */
	wpabuf_put_u8(buf, 0x7f); /* QueryRespLenLimit | PAME-BI */
	wpabuf_put_u8(buf, NATIVE_QUERY_PROTOCOL); /* Advertisement Protocol */

	/* Query Response */
	len_pos = wpabuf_put(buf, 2); /* Length (to be filled) */

	if (tlvs) {
		/* NQP Query Response Frame */
		wpabuf_put_le16(buf, NQP_VENDOR_SPECIFIC); /* Info ID */
		len_pos2 = wpabuf_put(buf, 2); /* Length (to be filled) */
		wpabuf_put_be24(buf, OUI_WFA);
		wpabuf_put_u8(buf, P2P_OUI_TYPE);
		 /* Service Update Indicator */
		wpabuf_put_le16(buf, update_indic);
		wpabuf_put_buf(buf, tlvs);

		WPA_PUT_LE16(len_pos2,
			     (u8 *) wpabuf_put(buf, 0) - len_pos2 - 2);
	}

	WPA_PUT_LE16(len_pos, (u8 *) wpabuf_put(buf, 0) - len_pos - 2);

	return buf;
}
Ejemplo n.º 30
0
static void anqp_add_elem(struct hostapd_data *hapd, struct wpabuf *buf,
			  u16 infoid)
{
	struct anqp_element *elem;

	elem = get_anqp_elem(hapd, infoid);
	if (!elem)
		return;
	if (wpabuf_tailroom(buf) < 2 + 2 + wpabuf_len(elem->payload)) {
		wpa_printf(MSG_DEBUG, "ANQP: No room for InfoID %u payload",
			   infoid);
		return;
	}

	wpabuf_put_le16(buf, infoid);
	wpabuf_put_le16(buf, wpabuf_len(elem->payload));
	wpabuf_put_buf(buf, elem->payload);
}