int wps_build_oob_dev_pw(struct wpabuf *msg, u16 dev_pw_id,
			 const struct wpabuf *pubkey, const u8 *dev_pw,
			 size_t dev_pw_len)
{
	size_t hash_len;
	const u8 *addr[1];
	u8 pubkey_hash[WPS_HASH_LEN];

	wpa_printf(MSG_DEBUG, "WPS:  * OOB Device Password (dev_pw_id=%u)",
		   dev_pw_id);
	addr[0] = wpabuf_head(pubkey);
	hash_len = wpabuf_len(pubkey);
	if (sha256_vector(1, addr, &hash_len, pubkey_hash) < 0)
		return -1;
#ifdef CONFIG_WPS_TESTING
	if (wps_corrupt_pkhash) {
		wpa_hexdump(MSG_DEBUG, "WPS: Real Public Key Hash",
			    pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN);
		wpa_printf(MSG_INFO, "WPS: Testing - corrupt public key hash");
		pubkey_hash[WPS_OOB_PUBKEY_HASH_LEN - 2]++;
	}
#endif /* CONFIG_WPS_TESTING */

	wpabuf_put_be16(msg, ATTR_OOB_DEVICE_PASSWORD);
	wpabuf_put_be16(msg, WPS_OOB_PUBKEY_HASH_LEN + 2 + dev_pw_len);
	wpa_hexdump(MSG_DEBUG, "WPS: Public Key Hash",
		    pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN);
	wpabuf_put_data(msg, pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN);
	wpabuf_put_be16(msg, dev_pw_id);
	if (dev_pw) {
		wpa_hexdump_key(MSG_DEBUG, "WPS: OOB Device Password",
				dev_pw, dev_pw_len);
		wpabuf_put_data(msg, dev_pw, dev_pw_len);
	}

	return 0;
}
Beispiel #2
0
static int eap_tlv_add_cryptobinding(struct eap_sm *sm,
				     struct eap_peap_data *data,
				     struct wpabuf *buf)
{
	u8 *mac;
	u8 eap_type = EAP_TYPE_PEAP;
	const u8 *addr[2];
	size_t len[2];
	u16 tlv_type;

	/* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */
	addr[0] = wpabuf_put(buf, 0);
	len[0] = 60;
	addr[1] = &eap_type;
	len[1] = 1;

	tlv_type = EAP_TLV_CRYPTO_BINDING_TLV;
	wpabuf_put_be16(buf, tlv_type);
	wpabuf_put_be16(buf, 56);

	wpabuf_put_u8(buf, 0); /* Reserved */
	wpabuf_put_u8(buf, data->peap_version); /* Version */
	wpabuf_put_u8(buf, data->peap_version); /* RecvVersion */
	wpabuf_put_u8(buf, 1); /* SubType: 0 = Request, 1 = Response */
	wpabuf_put_data(buf, data->binding_nonce, 32); /* Nonce */
	mac = wpabuf_put(buf, 20); /* Compound_MAC */
	wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC CMK", data->cmk, 20);
	wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 1",
		    addr[0], len[0]);
	wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 2",
		    addr[1], len[1]);
	hmac_sha1_vector(data->cmk, 20, 2, addr, len, mac);
	wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC", mac, SHA1_MAC_LEN);
	data->crypto_binding_used = 1;

	return 0;
}
Beispiel #3
0
static int wps_build_cred_network_key(struct wps_data *wps, struct wpabuf *msg)
{
	if ((wps->wps->ap_auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) &&
	    wps->wps->network_key_len == 0) {
		char hex[65];
		u8 psk[32];
		/* Generate a random per-device PSK */
		if (random_pool_ready() != 1 ||
		    random_get_bytes(psk, sizeof(psk)) < 0) {
			wpa_printf(MSG_INFO,
				   "WPS: Could not generate random PSK");
			return -1;
		}
		wpa_hexdump_key(MSG_DEBUG, "WPS: Generated per-device PSK",
				psk, sizeof(psk));
		wpa_printf(MSG_DEBUG, "WPS:  * Network Key (len=%u)",
			   (unsigned int) wps->new_psk_len * 2);
		wpa_snprintf_hex(hex, sizeof(hex), psk, sizeof(psk));
		wpabuf_put_be16(msg, ATTR_NETWORK_KEY);
		wpabuf_put_be16(msg, sizeof(psk) * 2);
		wpabuf_put_data(msg, hex, sizeof(psk) * 2);
		if (wps->wps->registrar) {
			wps_cb_new_psk(wps->wps->registrar,
				       wps->peer_dev.mac_addr,
				       wps->p2p_dev_addr, psk, sizeof(psk));
		}
		return 0;
	}

	wpa_printf(MSG_DEBUG, "WPS:  * Network Key (len=%u)",
		   (unsigned int) wps->wps->network_key_len);
	wpabuf_put_be16(msg, ATTR_NETWORK_KEY);
	wpabuf_put_be16(msg, wps->wps->network_key_len);
	wpabuf_put_data(msg, wps->wps->network_key, wps->wps->network_key_len);
	return 0;
}
Beispiel #4
0
struct wpabuf * tncs_build_soh_request(void)
{
    struct wpabuf *buf;

    /*
     * Build a SoH Request TLV (to be used inside SoH EAP Extensions
     * Method)
     */

    buf = wpabuf_alloc(8 + 4);
    if (buf == NULL)
        return NULL;

    /* Vendor-Specific TLV (Microsoft) - SoH Request */
    wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV); /* TLV Type */
    wpabuf_put_be16(buf, 8); /* Length */

    wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* Vendor_Id */

    wpabuf_put_be16(buf, 0x02); /* TLV Type - SoH Request TLV */
    wpabuf_put_be16(buf, 0); /* Length */

    return buf;
}
static struct wpabuf * eap_pax_build_std_3(struct eap_sm *sm,
					   struct eap_pax_data *data, u8 id)
{
	struct wpabuf *req;
	struct eap_pax_hdr *pax;
	u8 *pos;

	wpa_printf(MSG_DEBUG, "EAP-PAX: PAX_STD-3 (sending)");

	req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PAX,
			    sizeof(*pax) + 2 + EAP_PAX_MAC_LEN +
			    EAP_PAX_ICV_LEN, EAP_CODE_REQUEST, id);
	if (req == NULL) {
		wpa_printf(MSG_ERROR, "EAP-PAX: Failed to allocate memory "
			   "request");
		data->state = FAILURE;
		return NULL;
	}

	pax = wpabuf_put(req, sizeof(*pax));
	pax->op_code = EAP_PAX_OP_STD_3;
	pax->flags = 0;
	pax->mac_id = data->mac_id;
	pax->dh_group_id = EAP_PAX_DH_GROUP_NONE;
	pax->public_key_id = EAP_PAX_PUBLIC_KEY_NONE;

	wpabuf_put_be16(req, EAP_PAX_MAC_LEN);
	pos = wpabuf_put(req, EAP_PAX_MAC_LEN);
	eap_pax_mac(data->mac_id, data->ck, EAP_PAX_CK_LEN,
		    data->rand.r.y, EAP_PAX_RAND_LEN,
		    (u8 *) data->cid, data->cid_len, NULL, 0, pos);
	wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: MAC_CK(B, CID)",
		    pos, EAP_PAX_MAC_LEN);
	pos += EAP_PAX_MAC_LEN;

	/* Optional ADE could be added here, if needed */

	pos = wpabuf_put(req, EAP_PAX_MAC_LEN);
	eap_pax_mac(data->mac_id, data->ick, EAP_PAX_ICK_LEN,
		    wpabuf_mhead(req), wpabuf_len(req) - EAP_PAX_ICV_LEN,
		    NULL, 0, NULL, 0, pos);
	wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", pos, EAP_PAX_ICV_LEN);

	return req;
}
static struct wpabuf * eap_pax_build_std_1(struct eap_sm *sm,
					   struct eap_pax_data *data, u8 id)
{
	struct wpabuf *req;
	struct eap_pax_hdr *pax;
	u8 *pos;

	wpa_printf(MSG_DEBUG, "EAP-PAX: PAX_STD-1 (sending)");

	if (random_get_bytes(data->rand.r.x, EAP_PAX_RAND_LEN)) {
		wpa_printf(MSG_ERROR, "EAP-PAX: Failed to get random data");
		data->state = FAILURE;
		return NULL;
	}

	req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PAX,
			    sizeof(*pax) + 2 + EAP_PAX_RAND_LEN +
			    EAP_PAX_ICV_LEN, EAP_CODE_REQUEST, id);
	if (req == NULL) {
		wpa_printf(MSG_ERROR, "EAP-PAX: Failed to allocate memory "
			   "request");
		data->state = FAILURE;
		return NULL;
	}

	pax = wpabuf_put(req, sizeof(*pax));
	pax->op_code = EAP_PAX_OP_STD_1;
	pax->flags = 0;
	pax->mac_id = data->mac_id;
	pax->dh_group_id = EAP_PAX_DH_GROUP_NONE;
	pax->public_key_id = EAP_PAX_PUBLIC_KEY_NONE;

	wpabuf_put_be16(req, EAP_PAX_RAND_LEN);
	wpabuf_put_data(req, data->rand.r.x, EAP_PAX_RAND_LEN);
	wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: A = X (server rand)",
		    data->rand.r.x, EAP_PAX_RAND_LEN);

	pos = wpabuf_put(req, EAP_PAX_MAC_LEN);
	eap_pax_mac(data->mac_id, (u8 *) "", 0,
		    wpabuf_mhead(req), wpabuf_len(req) - EAP_PAX_ICV_LEN,
		    NULL, 0, NULL, 0, pos);
	wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", pos, EAP_PAX_ICV_LEN);

	return req;
}
Beispiel #7
0
int wps_build_vendor_extension_ms(struct wpabuf *msg, const u8 *uuid)
{
	//u8 ven_ext[VENDOR_EXT_MS_LEN];

	wpa_printf(MSG_DEBUG, "WPS:  * Microsoft Vendor Extension");
	wpabuf_put_be16(msg, ATTR_VENDOR_EXT);
	wpabuf_put_be16(msg, VENDOR_EXT_MS_LEN);

	wpabuf_put_be24(msg, VENDOR_ID_MICROSOFT);

	//TLV#1(VPI), The Profile Request field should only be set to a value of 0x01.
	wpabuf_put_be16(msg, TLV_VPI);
	wpabuf_put_be16(msg, 2);
	wpabuf_put_be16(msg, ((VPI_UPNP<<8)|0x01));

	//TLV#2(UUID)
	wpabuf_put_be16(msg, TLV_UUID);
	wpabuf_put_be16(msg, WPS_UUID_LEN);
	wpabuf_put_data(msg, uuid, WPS_UUID_LEN);
	
	return 0;
}
Beispiel #8
0
static struct wpabuf * eap_gpsk_send_gpsk_2(struct eap_gpsk_data *data,
        u8 identifier,
        const u8 *csuite_list,
        size_t csuite_list_len)
{
    struct wpabuf *resp;
    size_t len, miclen;
    u8 *rpos, *start;
    struct eap_gpsk_csuite *csuite;

    wpa_printf(MSG_DEBUG, "EAP-GPSK: Sending Response/GPSK-2");

    miclen = eap_gpsk_mic_len(data->vendor, data->specifier);
    len = 1 + 2 + data->id_peer_len + 2 + data->id_server_len +
          2 * EAP_GPSK_RAND_LEN + 2 + csuite_list_len +
          sizeof(struct eap_gpsk_csuite) + 2 + miclen;

    resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, len,
                         EAP_CODE_RESPONSE, identifier);
    if (resp == NULL)
        return NULL;

    wpabuf_put_u8(resp, EAP_GPSK_OPCODE_GPSK_2);
    start = wpabuf_put(resp, 0);

    wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Peer",
                      data->id_peer, data->id_peer_len);
    wpabuf_put_be16(resp, data->id_peer_len);
    wpabuf_put_data(resp, data->id_peer, data->id_peer_len);

    wpabuf_put_be16(resp, data->id_server_len);
    wpabuf_put_data(resp, data->id_server, data->id_server_len);

    if (os_get_random(data->rand_peer, EAP_GPSK_RAND_LEN)) {
        wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to get random data "
                   "for RAND_Peer");
        eap_gpsk_state(data, FAILURE);
        wpabuf_free(resp);
        return NULL;
    }
    wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer",
                data->rand_peer, EAP_GPSK_RAND_LEN);
    wpabuf_put_data(resp, data->rand_peer, EAP_GPSK_RAND_LEN);
    wpabuf_put_data(resp, data->rand_server, EAP_GPSK_RAND_LEN);

    wpabuf_put_be16(resp, csuite_list_len);
    wpabuf_put_data(resp, csuite_list, csuite_list_len);

    csuite = wpabuf_put(resp, sizeof(*csuite));
    WPA_PUT_BE32(csuite->vendor, data->vendor);
    WPA_PUT_BE16(csuite->specifier, data->specifier);

    if (eap_gpsk_derive_keys(data->psk, data->psk_len,
                             data->vendor, data->specifier,
                             data->rand_peer, data->rand_server,
                             data->id_peer, data->id_peer_len,
                             data->id_server, data->id_server_len,
                             data->msk, data->emsk,
                             data->sk, &data->sk_len,
                             data->pk, &data->pk_len) < 0) {
        wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to derive keys");
        eap_gpsk_state(data, FAILURE);
        wpabuf_free(resp);
        return NULL;
    }

    /* No PD_Payload_1 */
    wpabuf_put_be16(resp, 0);

    rpos = wpabuf_put(resp, miclen);
    if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor,
                             data->specifier, start, rpos - start, rpos) <
            0) {
        eap_gpsk_state(data, FAILURE);
        wpabuf_free(resp);
        return NULL;
    }

    return resp;
}
Beispiel #9
0
static struct wpabuf *
eap_pwd_build_req(struct eap_sm *sm, void *priv, u8 id)
{
	struct eap_pwd_data *data = priv;
	struct wpabuf *req;
	u8 lm_exch;
	const u8 *buf;
	u16 totlen = 0;
	size_t len;

	/*
	 * if we're buffering response fragments then just ACK
	 */
	if (data->in_frag_pos) {
		wpa_printf(MSG_DEBUG, "EAP-pwd: ACKing a fragment!!");
		req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD,
				    EAP_PWD_HDR_SIZE, EAP_CODE_REQUEST, id);
		if (req == NULL) {
			eap_pwd_state(data, FAILURE);
			return NULL;
		}
		switch (data->state) {
		case PWD_ID_Req:
			wpabuf_put_u8(req, EAP_PWD_OPCODE_ID_EXCH);
			break;
		case PWD_Commit_Req:
			wpabuf_put_u8(req, EAP_PWD_OPCODE_COMMIT_EXCH);
			break;
		case PWD_Confirm_Req:
			wpabuf_put_u8(req, EAP_PWD_OPCODE_CONFIRM_EXCH);
			break;
		default:
			eap_pwd_state(data, FAILURE);   /* just to be sure */
			wpabuf_free(req);
			return NULL;
		}
		return req;
	}

	/*
	 * build the data portion of a request
	 */
	switch (data->state) {
	case PWD_ID_Req:
		eap_pwd_build_id_req(sm, data, id);
		lm_exch = EAP_PWD_OPCODE_ID_EXCH;
		break;
	case PWD_Commit_Req:
		eap_pwd_build_commit_req(sm, data, id);
		lm_exch = EAP_PWD_OPCODE_COMMIT_EXCH;
		break;
	case PWD_Confirm_Req:
		eap_pwd_build_confirm_req(sm, data, id);
		lm_exch = EAP_PWD_OPCODE_CONFIRM_EXCH;
		break;
	default:
		wpa_printf(MSG_INFO, "EAP-pwd: Unknown state %d in build_req",
			   data->state);
		eap_pwd_state(data, FAILURE);
		lm_exch = 0;    /* hush now, sweet compiler */
		break;
	}

	if (data->state == FAILURE)
		return NULL;

	/*
	 * determine whether that data needs to be fragmented
	 */
	len = wpabuf_len(data->outbuf) - data->out_frag_pos;
	if ((len + EAP_PWD_HDR_SIZE) > data->mtu) {
		len = data->mtu - EAP_PWD_HDR_SIZE;
		EAP_PWD_SET_MORE_BIT(lm_exch);
		/*
		 * if this is the first fragment, need to set the M bit
		 * and add the total length to the eap_pwd_hdr
		 */
		if (data->out_frag_pos == 0) {
			EAP_PWD_SET_LENGTH_BIT(lm_exch);
			totlen = wpabuf_len(data->outbuf) +
				EAP_PWD_HDR_SIZE + sizeof(u16);
			len -= sizeof(u16);
			wpa_printf(MSG_DEBUG, "EAP-pwd: Fragmenting output, "
				   "total length = %d", totlen);
		}
		wpa_printf(MSG_DEBUG, "EAP-pwd: Send a %d byte fragment",
			   (int) len);
	}

	/*
	 * alloc an eap request and populate it with the data
	 */
	req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD,
			    EAP_PWD_HDR_SIZE + len +
			    (totlen ? sizeof(u16) : 0),
			    EAP_CODE_REQUEST, id);
	if (req == NULL) {
		eap_pwd_state(data, FAILURE);
		return NULL;
	}

	wpabuf_put_u8(req, lm_exch);
	if (EAP_PWD_GET_LENGTH_BIT(lm_exch))
		wpabuf_put_be16(req, totlen);

	buf = wpabuf_head_u8(data->outbuf);
	wpabuf_put_data(req, buf + data->out_frag_pos, len);
	data->out_frag_pos += len;
	/*
	 * either not fragged or last fragment, either way free up the data
	 */
	if (data->out_frag_pos >= wpabuf_len(data->outbuf)) {
		wpabuf_free(data->outbuf);
		data->outbuf = NULL;
		data->out_frag_pos = 0;
	}

	return req;
}
Beispiel #10
0
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;
}
Beispiel #11
0
static struct wpabuf * tncc_build_soh(int ver)
{
	struct wpabuf *buf;
	u8 *tlv_len, *tlv_len2, *outer_len, *inner_len, *ssoh_len, *end;
	u8 correlation_id[24];
	/* TODO: get correct name */
	char *machinename = "*****@*****.**";

	if (os_get_random(correlation_id, sizeof(correlation_id)))
		return NULL;
	wpa_hexdump(MSG_DEBUG, "TNC: SoH Correlation ID",
		    correlation_id, sizeof(correlation_id));

	buf = wpabuf_alloc(200);
	if (buf == NULL)
		return NULL;

	/* Vendor-Specific TLV (Microsoft) - SoH */
	wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV); /* TLV Type */
	tlv_len = wpabuf_put(buf, 2); /* Length */
	wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* Vendor_Id */
	wpabuf_put_be16(buf, 0x01); /* TLV Type - SoH TLV */
	tlv_len2 = wpabuf_put(buf, 2); /* Length */

	/* SoH Header */
	wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV); /* Outer Type */
	outer_len = wpabuf_put(buf, 2);
	wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* IANA SMI Code */
	wpabuf_put_be16(buf, ver); /* Inner Type */
	inner_len = wpabuf_put(buf, 2);

	if (ver == 2) {
		/* SoH Mode Sub-Header */
		/* Outer Type */
		wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV);
		wpabuf_put_be16(buf, 4 + 24 + 1 + 1); /* Length */
		wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* IANA SMI Code */
		/* Value: */
		wpabuf_put_data(buf, correlation_id, sizeof(correlation_id));
		wpabuf_put_u8(buf, 0x01); /* Intent Flag - Request */
		wpabuf_put_u8(buf, 0x00); /* Content-Type Flag */
	}

	/* SSoH TLV */
	/* System-Health-Id */
	wpabuf_put_be16(buf, 0x0002); /* Type */
	wpabuf_put_be16(buf, 4); /* Length */
	wpabuf_put_be32(buf, 79616);
	/* Vendor-Specific Attribute */
	wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV);
	ssoh_len = wpabuf_put(buf, 2);
	wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* IANA SMI Code */

	/* MS-Packet-Info */
	wpabuf_put_u8(buf, SSOH_MS_PACKET_INFO);
	/* Note: IF-TNCCS-SOH v1.0 r8 claims this field to be:
	 * Reserved(4 bits) r(1 bit) Vers(3 bits), but Windows XP
	 * SP3 seems to be sending 0x11 for SSoH, i.e., r(request/response) bit
	 * would not be in the specified location.
	 * [MS-SOH] 4.0.2: Reserved(3 bits) r(1 bit) Vers(4 bits)
	 */
	wpabuf_put_u8(buf, 0x11); /* r=request, vers=1 */

	/* MS-Machine-Inventory */
	/* TODO: get correct values; 0 = not applicable for OS */
	wpabuf_put_u8(buf, SSOH_MS_MACHINE_INVENTORY);
	wpabuf_put_be32(buf, 0); /* osVersionMajor */
	wpabuf_put_be32(buf, 0); /* osVersionMinor */
	wpabuf_put_be32(buf, 0); /* osVersionBuild */
	wpabuf_put_be16(buf, 0); /* spVersionMajor */
	wpabuf_put_be16(buf, 0); /* spVersionMinor */
	wpabuf_put_be16(buf, 0); /* procArch */

	/* MS-MachineName */
	wpabuf_put_u8(buf, SSOH_MS_MACHINENAME);
	wpabuf_put_be16(buf, os_strlen(machinename) + 1);
	wpabuf_put_data(buf, machinename, os_strlen(machinename) + 1);

	/* MS-CorrelationId */
	wpabuf_put_u8(buf, SSOH_MS_CORRELATIONID);
	wpabuf_put_data(buf, correlation_id, sizeof(correlation_id));

	/* MS-Quarantine-State */
	wpabuf_put_u8(buf, SSOH_MS_QUARANTINE_STATE);
	wpabuf_put_be16(buf, 1); /* Flags: ExtState=0, f=0, qState=1 */
	wpabuf_put_be32(buf, 0xffffffff); /* ProbTime (hi) */
	wpabuf_put_be32(buf, 0xffffffff); /* ProbTime (lo) */
	wpabuf_put_be16(buf, 1); /* urlLenInBytes */
	wpabuf_put_u8(buf, 0); /* null termination for the url */

	/* MS-Machine-Inventory-Ex */
	wpabuf_put_u8(buf, SSOH_MS_MACHINE_INVENTORY_EX);
	wpabuf_put_be32(buf, 0); /* Reserved
				  * (note: Windows XP SP3 uses 0xdecafbad) */
	wpabuf_put_u8(buf, 1); /* ProductType: Client */

	/* Update SSoH Length */
	end = wpabuf_put(buf, 0);
	WPA_PUT_BE16(ssoh_len, end - ssoh_len - 2);

	/* TODO: SoHReportEntry TLV (zero or more) */

	/* Update length fields */
	end = wpabuf_put(buf, 0);
	WPA_PUT_BE16(tlv_len, end - tlv_len - 2);
	WPA_PUT_BE16(tlv_len2, end - tlv_len2 - 2);
	WPA_PUT_BE16(outer_len, end - outer_len - 2);
	WPA_PUT_BE16(inner_len, end - inner_len - 2);

	return buf;
}
static struct wpabuf * eap_fast_build_pac(struct eap_sm *sm,
					  struct eap_fast_data *data)
{
	u8 pac_key[EAP_FAST_PAC_KEY_LEN];
	u8 *pac_buf, *pac_opaque;
	struct wpabuf *buf;
	u8 *pos;
	size_t buf_len, srv_id_info_len, pac_len;
	struct eap_tlv_hdr *pac_tlv;
	struct pac_tlv_hdr *pac_info;
	struct eap_tlv_result_tlv *result;
	struct os_time now;

	if (random_get_bytes(pac_key, EAP_FAST_PAC_KEY_LEN) < 0 ||
	    os_get_time(&now) < 0)
		return NULL;
	wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Generated PAC-Key",
			pac_key, EAP_FAST_PAC_KEY_LEN);

	pac_len = (2 + EAP_FAST_PAC_KEY_LEN) + (2 + 4) +
		(2 + sm->identity_len) + 8;
	pac_buf = os_malloc(pac_len);
	if (pac_buf == NULL)
		return NULL;

	srv_id_info_len = os_strlen(data->srv_id_info);

	pos = pac_buf;
	*pos++ = PAC_OPAQUE_TYPE_KEY;
	*pos++ = EAP_FAST_PAC_KEY_LEN;
	os_memcpy(pos, pac_key, EAP_FAST_PAC_KEY_LEN);
	pos += EAP_FAST_PAC_KEY_LEN;

	*pos++ = PAC_OPAQUE_TYPE_LIFETIME;
	*pos++ = 4;
	WPA_PUT_BE32(pos, now.sec + data->pac_key_lifetime);
	pos += 4;

	if (sm->identity) {
		*pos++ = PAC_OPAQUE_TYPE_IDENTITY;
		*pos++ = sm->identity_len;
		os_memcpy(pos, sm->identity, sm->identity_len);
		pos += sm->identity_len;
	}

	pac_len = pos - pac_buf;
	while (pac_len % 8) {
		*pos++ = PAC_OPAQUE_TYPE_PAD;
		pac_len++;
	}

	pac_opaque = os_malloc(pac_len + 8);
	if (pac_opaque == NULL) {
		os_free(pac_buf);
		return NULL;
	}
	if (aes_wrap(data->pac_opaque_encr, sizeof(data->pac_opaque_encr),
		     pac_len / 8, pac_buf, pac_opaque) < 0) {
		os_free(pac_buf);
		os_free(pac_opaque);
		return NULL;
	}
	os_free(pac_buf);

	pac_len += 8;
	wpa_hexdump(MSG_DEBUG, "EAP-FAST: PAC-Opaque",
		    pac_opaque, pac_len);

	buf_len = sizeof(*pac_tlv) +
		sizeof(struct pac_tlv_hdr) + EAP_FAST_PAC_KEY_LEN +
		sizeof(struct pac_tlv_hdr) + pac_len +
		data->srv_id_len + srv_id_info_len + 100 + sizeof(*result);
	buf = wpabuf_alloc(buf_len);
	if (buf == NULL) {
		os_free(pac_opaque);
		return NULL;
	}

	/* Result TLV */
	wpa_printf(MSG_DEBUG, "EAP-FAST: Add Result TLV (status=SUCCESS)");
	result = wpabuf_put(buf, sizeof(*result));
	WPA_PUT_BE16((u8 *) &result->tlv_type,
		     EAP_TLV_TYPE_MANDATORY | EAP_TLV_RESULT_TLV);
	WPA_PUT_BE16((u8 *) &result->length, 2);
	WPA_PUT_BE16((u8 *) &result->status, EAP_TLV_RESULT_SUCCESS);

	/* PAC TLV */
	wpa_printf(MSG_DEBUG, "EAP-FAST: Add PAC TLV");
	pac_tlv = wpabuf_put(buf, sizeof(*pac_tlv));
	pac_tlv->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY |
					 EAP_TLV_PAC_TLV);

	/* PAC-Key */
	eap_fast_put_tlv(buf, PAC_TYPE_PAC_KEY, pac_key, EAP_FAST_PAC_KEY_LEN);

	/* PAC-Opaque */
	eap_fast_put_tlv(buf, PAC_TYPE_PAC_OPAQUE, pac_opaque, pac_len);
	os_free(pac_opaque);

	/* PAC-Info */
	pac_info = wpabuf_put(buf, sizeof(*pac_info));
	pac_info->type = host_to_be16(PAC_TYPE_PAC_INFO);

	/* PAC-Lifetime (inside PAC-Info) */
	eap_fast_put_tlv_hdr(buf, PAC_TYPE_CRED_LIFETIME, 4);
	wpabuf_put_be32(buf, now.sec + data->pac_key_lifetime);

	/* A-ID (inside PAC-Info) */
	eap_fast_put_tlv(buf, PAC_TYPE_A_ID, data->srv_id, data->srv_id_len);
	
	/* Note: headers may be misaligned after A-ID */

	if (sm->identity) {
		eap_fast_put_tlv(buf, PAC_TYPE_I_ID, sm->identity,
				 sm->identity_len);
	}

	/* A-ID-Info (inside PAC-Info) */
	eap_fast_put_tlv(buf, PAC_TYPE_A_ID_INFO, data->srv_id_info,
			 srv_id_info_len);

	/* PAC-Type (inside PAC-Info) */
	eap_fast_put_tlv_hdr(buf, PAC_TYPE_PAC_TYPE, 2);
	wpabuf_put_be16(buf, PAC_TYPE_TUNNEL_PAC);

	/* Update PAC-Info and PAC TLV Length fields */
	pos = wpabuf_put(buf, 0);
	pac_info->len = host_to_be16(pos - (u8 *) (pac_info + 1));
	pac_tlv->length = host_to_be16(pos - (u8 *) (pac_tlv + 1));

	return buf;
}
Beispiel #13
0
static int p2p_buf_add_service_info(struct wpabuf *buf, struct p2p_data *p2p,
				    u32 adv_id, u16 config_methods,
				    const char *svc_name, u8 **ie_len, u8 **pos,
				    size_t *total_len, u8 *attr_len)
{
	size_t svc_len;
	size_t remaining;
	size_t info_len;

	p2p_dbg(p2p, "Add service info for %s (adv_id=%u)", svc_name, adv_id);
	svc_len = os_strlen(svc_name);
	info_len = sizeof(adv_id) + sizeof(config_methods) + sizeof(u8) +
		svc_len;

	if (info_len + *total_len > MAX_SVC_ADV_LEN) {
		p2p_dbg(p2p,
			"Unsufficient buffer, failed to add advertised service info");
		return -1;
	}

	if (svc_len > 255) {
		p2p_dbg(p2p,
			"Invalid service name length (%u bytes), failed to add advertised service info",
			(unsigned int) svc_len);
		return -1;
	}

	if (*ie_len) {
		int ie_data_len = (*pos - *ie_len) - 1;

		if (ie_data_len < 0 || ie_data_len > 255) {
			p2p_dbg(p2p,
				"Invalid IE length, failed to add advertised service info");
			return -1;
		}
		remaining = 255 - ie_data_len;
	} else {
		/*
		 * Adding new P2P IE header takes 6 extra bytes:
		 * - 2 byte IE header (1 byte IE id and 1 byte length)
		 * - 4 bytes of IE_VENDOR_TYPE are reduced from 255 below
		 */
		*ie_len = p2p_buf_add_ie_hdr(buf);
		remaining = 255 - 4;
	}

	if (remaining < sizeof(u32) + sizeof(u16) + sizeof(u8)) {
		/*
		 * Split adv_id, config_methods, and svc_name_len between two
		 * IEs.
		 */
		size_t front = remaining;
		size_t back = sizeof(u32) + sizeof(u16) + sizeof(u8) - front;
		u8 holder[sizeof(u32) + sizeof(u16) + sizeof(u8)];

		WPA_PUT_LE32(holder, adv_id);
		WPA_PUT_BE16(&holder[sizeof(u32)], config_methods);
		holder[sizeof(u32) + sizeof(u16)] = svc_len;

		if (front)
			wpabuf_put_data(buf, holder, front);

		p2p_buf_update_ie_hdr(buf, *ie_len);
		*ie_len = p2p_buf_add_ie_hdr(buf);

		wpabuf_put_data(buf, &holder[front], back);
		remaining = 255 - 4 - (sizeof(u32) + sizeof(u16) + sizeof(u8)) -
			back;
	} else {
		wpabuf_put_le32(buf, adv_id);
		wpabuf_put_be16(buf, config_methods);
		wpabuf_put_u8(buf, svc_len);
		remaining -= sizeof(adv_id) + sizeof(config_methods) +
			sizeof(u8);
	}

	if (remaining < svc_len) {
		/* split svc_name between two or three IEs */
		size_t front = remaining;
		size_t back = svc_len - front;

		if (front)
			wpabuf_put_data(buf, svc_name, front);

		p2p_buf_update_ie_hdr(buf, *ie_len);
		*ie_len = p2p_buf_add_ie_hdr(buf);

		/* In rare cases, we must split across 3 attributes */
		if (back > 255 - 4) {
			wpabuf_put_data(buf, &svc_name[front], 255 - 4);
			back -= 255 - 4;
			front += 255 - 4;
			p2p_buf_update_ie_hdr(buf, *ie_len);
			*ie_len = p2p_buf_add_ie_hdr(buf);
		}

		wpabuf_put_data(buf, &svc_name[front], back);
		remaining = 255 - 4 - back;
	} else {
		wpabuf_put_data(buf, svc_name, svc_len);
		remaining -= svc_len;
	}

	p2p_buf_update_ie_hdr(buf, *ie_len);

	/* set *ie_len to NULL if a new IE has to be added on the next call */
	if (!remaining)
		*ie_len = NULL;

	/* set *pos to point to the next byte to update */
	*pos = wpabuf_put(buf, 0);

	*total_len += info_len;
	WPA_PUT_LE16(attr_len, (u16) *total_len);
	return 0;
}
int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg)
{
	struct wpabuf *pubkey = NULL;

	wpa_printf(MSG_DEBUG, "WPS:  * Public Key");
	wpabuf_clear_free(wps->dh_privkey);
	wps->dh_privkey = NULL;
	if (wps->dev_pw_id != DEV_PW_DEFAULT && wps->wps->dh_privkey &&
	    wps->wps->dh_ctx) {
		wpa_printf(MSG_DEBUG, "WPS: Using pre-configured DH keys");
		if (wps->wps->dh_pubkey == NULL) {
			wpa_printf(MSG_DEBUG,
				   "WPS: wps->wps->dh_pubkey == NULL");
			return -1;
		}
		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->dev_pw_id == DEV_PW_NFC_CONNECTION_HANDOVER) &&
		   (wps->wps->ap ||
		    (wps->wps->ap_nfc_dh_pubkey &&
		     wps->wps->ap_nfc_dev_pw_id ==
		     DEV_PW_NFC_CONNECTION_HANDOVER &&
		     wps->dev_pw_id == DEV_PW_NFC_CONNECTION_HANDOVER)) &&
		   (wps->dev_pw_id == wps->wps->ap_nfc_dev_pw_id ||
		    wps->wps->ap_nfc_dh_pubkey)) {
		wpa_printf(MSG_DEBUG, "WPS: Using NFC password token DH keys");
		if (wps->wps->ap_nfc_dh_privkey == NULL) {
			wpa_printf(MSG_DEBUG,
				   "WPS: wps->wps->ap_nfc_dh_privkey == NULL");
			return -1;
		}
		if (wps->wps->ap_nfc_dh_pubkey == NULL) {
			wpa_printf(MSG_DEBUG,
				   "WPS: wps->wps->ap_nfc_dh_pubkey == NULL");
			return -1;
		}
		wps->dh_privkey = wpabuf_dup(wps->wps->ap_nfc_dh_privkey);
		pubkey = wpabuf_dup(wps->wps->ap_nfc_dh_pubkey);
		if (wps->dh_privkey && 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");
		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;
}
struct wpabuf * ndef_build_wifi_hr(void)
{
	struct wpabuf *rn, *cr, *ac_payload, *ac, *hr_payload, *hr;
	struct wpabuf *hc;

	rn = wpabuf_alloc(2);
	if (rn == NULL)
		return NULL;
	wpabuf_put_be16(rn, os_random() & 0xffff);

	cr = ndef_build_record(FLAG_MESSAGE_BEGIN | FLAG_TNF_NFC_FORUM, "cr", 2,
			       NULL, 0, rn);
	wpabuf_free(rn);

	if (cr == NULL)
		return NULL;

	ac_payload = wpabuf_alloc(4);
	if (ac_payload == NULL) {
		wpabuf_free(cr);
		return NULL;
	}
	wpabuf_put_u8(ac_payload, 0x01); /* Carrier Flags: CRS=1 "active" */
	wpabuf_put_u8(ac_payload, 0x01); /* Carrier Data Reference Length */
	wpabuf_put_u8(ac_payload, '0'); /* Carrier Data Reference: "0" */
	wpabuf_put_u8(ac_payload, 0); /* Aux Data Reference Count */

	ac = ndef_build_record(FLAG_MESSAGE_END | FLAG_TNF_NFC_FORUM, "ac", 2,
			       NULL, 0, ac_payload);
	wpabuf_free(ac_payload);
	if (ac == NULL) {
		wpabuf_free(cr);
		return NULL;
	}

	hr_payload = wpabuf_alloc(1 + wpabuf_len(cr) + wpabuf_len(ac));
	if (hr_payload == NULL) {
		wpabuf_free(cr);
		wpabuf_free(ac);
		return NULL;
	}

	wpabuf_put_u8(hr_payload, 0x12); /* Connection Handover Version 1.2 */
	wpabuf_put_buf(hr_payload, cr);
	wpabuf_put_buf(hr_payload, ac);
	wpabuf_free(cr);
	wpabuf_free(ac);

	hr = ndef_build_record(FLAG_MESSAGE_BEGIN | FLAG_TNF_NFC_FORUM, "Hr", 2,
			       NULL, 0, hr_payload);
	wpabuf_free(hr_payload);
	if (hr == NULL)
		return NULL;

	hc = ndef_build_wifi_hc(0);
	if (hc == NULL) {
		wpabuf_free(hr);
		return NULL;
	}

	return wpabuf_concat(hr, hc);
}
static struct wpabuf *
eap_pwd_process(struct eap_sm *sm, void *priv, struct eap_method_ret *ret,
		const struct wpabuf *reqData)
{
	struct eap_pwd_data *data = priv;
	struct wpabuf *resp = NULL;
	const u8 *pos, *buf;
	size_t len;
	u16 tot_len = 0;
	u8 lm_exch;

	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PWD, reqData, &len);
	if ((pos == NULL) || (len < 1)) {
		wpa_printf(MSG_DEBUG, "EAP-pwd: Got a frame but pos is %s and "
			   "len is %d",
			   pos == NULL ? "NULL" : "not NULL", (int) len);
		ret->ignore = TRUE;
		return NULL;
	}

	ret->ignore = FALSE;
	ret->methodState = METHOD_MAY_CONT;
	ret->decision = DECISION_FAIL;
	ret->allowNotifications = FALSE;

	lm_exch = *pos;
	pos++;                  /* skip over the bits and the exch */
	len--;

	/*
	 * we're fragmenting so send out the next fragment
	 */
	if (data->out_frag_pos) {
		/*
		 * this should be an ACK
		 */
		if (len)
			wpa_printf(MSG_INFO, "Bad Response! Fragmenting but "
				   "not an ACK");

		wpa_printf(MSG_DEBUG, "EAP-pwd: Got an ACK for a fragment");
		/*
		 * check if there are going to be more fragments
		 */
		len = wpabuf_len(data->outbuf) - data->out_frag_pos;
		if ((len + EAP_PWD_HDR_SIZE) > data->mtu) {
			len = data->mtu - EAP_PWD_HDR_SIZE;
			EAP_PWD_SET_MORE_BIT(lm_exch);
		}
		resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD,
				     EAP_PWD_HDR_SIZE + len,
				     EAP_CODE_RESPONSE, eap_get_id(reqData));
		if (resp == NULL) {
			wpa_printf(MSG_INFO, "Unable to allocate memory for "
				   "next fragment!");
			return NULL;
		}
		wpabuf_put_u8(resp, lm_exch);
		buf = wpabuf_head_u8(data->outbuf);
		wpabuf_put_data(resp, buf + data->out_frag_pos, len);
		data->out_frag_pos += len;
		/*
		 * this is the last fragment so get rid of the out buffer
		 */
		if (data->out_frag_pos >= wpabuf_len(data->outbuf)) {
			wpabuf_free(data->outbuf);
			data->outbuf = NULL;
			data->out_frag_pos = 0;
		}
		wpa_printf(MSG_DEBUG, "EAP-pwd: Send %s fragment of %d bytes",
			   data->out_frag_pos == 0 ? "last" : "next",
			   (int) len);
		return resp;
	}

	/*
	 * see if this is a fragment that needs buffering
	 *
	 * if it's the first fragment there'll be a length field
	 */
	if (EAP_PWD_GET_LENGTH_BIT(lm_exch)) {
		tot_len = WPA_GET_BE16(pos);
		wpa_printf(MSG_DEBUG, "EAP-pwd: Incoming fragments whose "
			   "total length = %d", tot_len);
		data->inbuf = wpabuf_alloc(tot_len);
		if (data->inbuf == NULL) {
			wpa_printf(MSG_INFO, "Out of memory to buffer "
				   "fragments!");
			return NULL;
		}
		pos += sizeof(u16);
		len -= sizeof(u16);
	}
	/*
	 * buffer and ACK the fragment
	 */
	if (EAP_PWD_GET_MORE_BIT(lm_exch)) {
		data->in_frag_pos += len;
		if (data->in_frag_pos > wpabuf_size(data->inbuf)) {
			wpa_printf(MSG_INFO, "EAP-pwd: Buffer overflow attack "
				   "detected (%d vs. %d)!",
				   (int) data->in_frag_pos,
				   (int) wpabuf_len(data->inbuf));
			wpabuf_free(data->inbuf);
			data->in_frag_pos = 0;
			return NULL;
		}
		wpabuf_put_data(data->inbuf, pos, len);

		resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD,
				     EAP_PWD_HDR_SIZE,
				     EAP_CODE_RESPONSE, eap_get_id(reqData));
		if (resp != NULL)
			wpabuf_put_u8(resp, (EAP_PWD_GET_EXCHANGE(lm_exch)));
		wpa_printf(MSG_DEBUG, "EAP-pwd: ACKing a %d byte fragment",
			   (int) len);
		return resp;
	}
	/*
	 * we're buffering and this is the last fragment
	 */
	if (data->in_frag_pos) {
		wpabuf_put_data(data->inbuf, pos, len);
		wpa_printf(MSG_DEBUG, "EAP-pwd: Last fragment, %d bytes",
			   (int) len);
		data->in_frag_pos += len;
		pos = wpabuf_head_u8(data->inbuf);
		len = data->in_frag_pos;
	}
	wpa_printf(MSG_DEBUG, "EAP-pwd: processing frame: exch %d, len %d",
		   EAP_PWD_GET_EXCHANGE(lm_exch), (int) len);

	switch (EAP_PWD_GET_EXCHANGE(lm_exch)) {
	case EAP_PWD_OPCODE_ID_EXCH:
		eap_pwd_perform_id_exchange(sm, data, ret, reqData,
					    pos, len);
		break;
	case EAP_PWD_OPCODE_COMMIT_EXCH:
		eap_pwd_perform_commit_exchange(sm, data, ret, reqData,
						pos, len);
		break;
	case EAP_PWD_OPCODE_CONFIRM_EXCH:
		eap_pwd_perform_confirm_exchange(sm, data, ret, reqData,
						 pos, len);
		break;
	default:
		wpa_printf(MSG_INFO, "EAP-pwd: Ignoring message with unknown "
			   "opcode %d", lm_exch);
		break;
	}
	/*
	 * if we buffered the just processed input now's the time to free it
	 */
	if (data->in_frag_pos) {
		wpabuf_free(data->inbuf);
		data->in_frag_pos = 0;
	}

	if (data->outbuf == NULL)
		return NULL;        /* generic failure */

	/*
	 * we have output! Do we need to fragment it?
	 */
	len = wpabuf_len(data->outbuf);
	if ((len + EAP_PWD_HDR_SIZE) > data->mtu) {
		resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD, data->mtu,
				     EAP_CODE_RESPONSE, eap_get_id(reqData));
		/*
		 * if so it's the first so include a length field
		 */
		EAP_PWD_SET_LENGTH_BIT(lm_exch);
		EAP_PWD_SET_MORE_BIT(lm_exch);
		tot_len = len;
		/*
		 * keep the packet at the MTU
		 */
		len = data->mtu - EAP_PWD_HDR_SIZE - sizeof(u16);
		wpa_printf(MSG_DEBUG, "EAP-pwd: Fragmenting output, total "
			   "length = %d", tot_len);
	} else {
		resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD,
				     EAP_PWD_HDR_SIZE + len,
				     EAP_CODE_RESPONSE, eap_get_id(reqData));
	}
	if (resp == NULL)
		return NULL;

	wpabuf_put_u8(resp, lm_exch);
	if (EAP_PWD_GET_LENGTH_BIT(lm_exch)) {
		wpabuf_put_be16(resp, tot_len);
		data->out_frag_pos += len;
	}
	buf = wpabuf_head_u8(data->outbuf);
	wpabuf_put_data(resp, buf, len);
	/*
	 * if we're not fragmenting then there's no need to carry this around
	 */
	if (data->out_frag_pos == 0) {
		wpabuf_free(data->outbuf);
		data->outbuf = NULL;
		data->out_frag_pos = 0;
	}

	return resp;
}
Beispiel #17
0
static struct wpabuf * eap_wsc_build_msg(struct eap_wsc_data *data,
					 struct eap_method_ret *ret, u8 id)
{
	struct wpabuf *resp;
	u8 flags;
	size_t send_len, plen;

	ret->ignore = FALSE;
	wpa_printf(MSG_DEBUG, "EAP-WSC: Generating Response");
	ret->allowNotifications = TRUE;

	flags = 0;
	send_len = wpabuf_len(data->out_buf) - data->out_used;
	if (2 + send_len > data->fragment_size) {
		send_len = data->fragment_size - 2;
		flags |= WSC_FLAGS_MF;
		if (data->out_used == 0) {
			flags |= WSC_FLAGS_LF;
			send_len -= 2;
		}
	}
	plen = 2 + send_len;
	if (flags & WSC_FLAGS_LF)
		plen += 2;
	resp = eap_msg_alloc(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, plen,
			     EAP_CODE_RESPONSE, id);
	if (resp == NULL)
		return NULL;

	wpabuf_put_u8(resp, data->out_op_code); /* Op-Code */
	wpabuf_put_u8(resp, flags); /* Flags */
	if (flags & WSC_FLAGS_LF)
		wpabuf_put_be16(resp, wpabuf_len(data->out_buf));

	wpabuf_put_data(resp, wpabuf_head_u8(data->out_buf) + data->out_used,
			send_len);
	data->out_used += send_len;

	ret->methodState = METHOD_MAY_CONT;
	ret->decision = DECISION_FAIL;

	if (data->out_used == wpabuf_len(data->out_buf)) {
		wpa_printf(MSG_DEBUG, "EAP-WSC: Sending out %lu bytes "
			   "(message sent completely)",
			   (unsigned long) send_len);
		wpabuf_free(data->out_buf);
		data->out_buf = NULL;
		data->out_used = 0;
		if ((data->state == FAIL && data->out_op_code == WSC_ACK) ||
		    data->out_op_code == WSC_NACK ||
		    data->out_op_code == WSC_Done) {
			eap_wsc_state(data, FAIL);
			ret->methodState = METHOD_DONE;
		} else
			eap_wsc_state(data, MESG);
	} else {
		wpa_printf(MSG_DEBUG, "EAP-WSC: Sending out %lu bytes "
			   "(%lu more to send)", (unsigned long) send_len,
			   (unsigned long) wpabuf_len(data->out_buf) -
			   data->out_used);
		eap_wsc_state(data, WAIT_FRAG_ACK);
	}

	return resp;
}
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;

        unsigned char *v;
        v = wpabuf_mhead_u8(pubkey);

        memset(pixie_pkr, 0, sizeof (pixie_pkr));
        if (get_debug() == 4) { //verbose (-vvv)
            printf("[P] PKR: ");
        }
        int pixiecnt = 0;
        for (; pixiecnt < 192; pixiecnt++) {
            if (get_debug() == 4) { //verbose (-vvv)
                printf("%02x", v[pixiecnt]);
            }
            sprintf(cmd_pixie_aux, "%02x", v[pixiecnt]);
            strcat(pixie_pkr, cmd_pixie_aux);
            if (pixiecnt != 191) {
                if (get_debug() == 4) { //verbose (-vvv)
                    printf(":");
                }
                strcat(pixie_pkr, ":");
            }
        }
        if (get_debug() == 4) { //verbose (-vvv)
            printf("\n");
        }



    } else {
        wpabuf_free(wps->dh_pubkey_e);
        wps->dh_pubkey_e = pubkey;
    }


    return 0;
}
int wps_build_wfa_ext(struct wpabuf *msg, int req_to_enroll,
		      const u8 *auth_macs, size_t auth_macs_count)
{
#ifdef CONFIG_CUSTOM_WFD
if (enable_widi_ve == 1)
{
            int i;
            u8 *len;

            wpabuf_put_be16(msg, ATTR_VENDOR_EXT);
            len = wpabuf_put(msg, 2); /* to be filled */
            wpabuf_put_be24(msg, WPS_WIDI_SINK_VENDOR_OUI); /* must match with Source OUI */
            wpabuf_put_u8(msg, 0x2);          //REMOTE DISPLAY
            wpabuf_put_be16(msg, 0x0003);     //REMOTE DISPLAY Sink Info
            wpabuf_put_be16(msg, 0x000b);     //Length of data that follows
		
            for (i=0; i < 11 ;i++)
            {
                wpabuf_put_u8(msg, fill_sink_info[i]);   //sink info
            }
		
            WPA_PUT_BE16(len, (u8 *) wpabuf_put(msg, 0) - len - 2);
} else {
#endif /* CONFIG_CUSTOM_WFD */
#ifdef CONFIG_WPS2
	u8 *len;

	wpabuf_put_be16(msg, ATTR_VENDOR_EXT);
	len = wpabuf_put(msg, 2); /* to be filled */
	wpabuf_put_be24(msg, WPS_VENDOR_ID_WFA);

	wpa_printf(MSG_DEBUG, "WPS:  * Version2 (0x%x)", WPS_VERSION);
	wpabuf_put_u8(msg, WFA_ELEM_VERSION2);
	wpabuf_put_u8(msg, 1);
	wpabuf_put_u8(msg, WPS_VERSION);

	if (req_to_enroll) {
		wpa_printf(MSG_DEBUG, "WPS:  * Request to Enroll (1)");
		wpabuf_put_u8(msg, WFA_ELEM_REQUEST_TO_ENROLL);
		wpabuf_put_u8(msg, 1);
		wpabuf_put_u8(msg, 1);
	}

	if (auth_macs && auth_macs_count) {
		size_t i;
		wpa_printf(MSG_DEBUG, "WPS:  * AuthorizedMACs (count=%d)",
			   (int) auth_macs_count);
		wpabuf_put_u8(msg, WFA_ELEM_AUTHORIZEDMACS);
		wpabuf_put_u8(msg, auth_macs_count * ETH_ALEN);
		wpabuf_put_data(msg, auth_macs, auth_macs_count * ETH_ALEN);
		for (i = 0; i < auth_macs_count; i++)
			wpa_printf(MSG_DEBUG, "WPS:    AuthorizedMAC: " MACSTR,
				   MAC2STR(&auth_macs[i * ETH_ALEN]));
	}

	WPA_PUT_BE16(len, (u8 *) wpabuf_put(msg, 0) - len - 2);
#endif /* CONFIG_WPS2 */
#ifdef CONFIG_CUSTOM_WFD
}
#endif /* CONFIG_CUSTOM_WFD */

#ifdef CONFIG_WPS_TESTING
	if (WPS_VERSION > 0x20) {
		wpa_printf(MSG_DEBUG, "WPS:  * Extensibility Testing - extra "
			   "attribute");
		wpabuf_put_be16(msg, ATTR_EXTENSIBILITY_TEST);
		wpabuf_put_be16(msg, 1);
		wpabuf_put_u8(msg, 42);
	}
#endif /* CONFIG_WPS_TESTING */
	return 0;
}
Beispiel #20
0
static int ikev2_build_sar1(struct ikev2_responder_data *data,
			    struct wpabuf *msg, u8 next_payload)
{
	struct ikev2_payload_hdr *phdr;
	size_t plen;
	struct ikev2_proposal *p;
	struct ikev2_transform *t;

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

	/* SAr1 - RFC 4306, Sect. 2.7 and 3.3 */
	phdr = wpabuf_put(msg, sizeof(*phdr));
	phdr->next_payload = next_payload;
	phdr->flags = 0;

	p = wpabuf_put(msg, sizeof(*p));
#ifdef CCNS_PL
	/* Seems to require that the Proposal # is 1 even though RFC 4306
	 * Sect 3.3.1 has following requirement "When a proposal is accepted,
	 * all of the proposal numbers in the SA payload MUST be the same and
	 * MUST match the number on the proposal sent that was accepted.".
	 */
	p->proposal_num = 1;
#else /* CCNS_PL */
	p->proposal_num = data->proposal.proposal_num;
#endif /* CCNS_PL */
	p->protocol_id = IKEV2_PROTOCOL_IKE;
	p->num_transforms = 4;

	t = wpabuf_put(msg, sizeof(*t));
	t->type = 3;
	t->transform_type = IKEV2_TRANSFORM_ENCR;
	WPA_PUT_BE16(t->transform_id, data->proposal.encr);
	if (data->proposal.encr == ENCR_AES_CBC) {
		/* Transform Attribute: Key Len = 128 bits */
#ifdef CCNS_PL
		wpabuf_put_be16(msg, 0x001d); /* ?? */
#else /* CCNS_PL */
		wpabuf_put_be16(msg, 0x800e); /* AF=1, AttrType=14 */
#endif /* CCNS_PL */
		wpabuf_put_be16(msg, 128); /* 128-bit key */
	}
	plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) t;
	WPA_PUT_BE16(t->transform_length, plen);

	t = wpabuf_put(msg, sizeof(*t));
	t->type = 3;
	WPA_PUT_BE16(t->transform_length, sizeof(*t));
	t->transform_type = IKEV2_TRANSFORM_PRF;
	WPA_PUT_BE16(t->transform_id, data->proposal.prf);

	t = wpabuf_put(msg, sizeof(*t));
	t->type = 3;
	WPA_PUT_BE16(t->transform_length, sizeof(*t));
	t->transform_type = IKEV2_TRANSFORM_INTEG;
	WPA_PUT_BE16(t->transform_id, data->proposal.integ);

	t = wpabuf_put(msg, sizeof(*t));
	WPA_PUT_BE16(t->transform_length, sizeof(*t));
	t->transform_type = IKEV2_TRANSFORM_DH;
	WPA_PUT_BE16(t->transform_id, data->proposal.dh);

	plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) p;
	WPA_PUT_BE16(p->proposal_length, plen);

	plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr;
	WPA_PUT_BE16(phdr->payload_length, plen);

	return 0;
}
Beispiel #21
0
static struct wpabuf * eap_peap_build_phase2_tlv(struct eap_sm *sm,
						 struct eap_peap_data *data,
						 u8 id)
{
	struct wpabuf *buf, *encr_req;
	size_t mlen;

	mlen = 6; /* Result TLV */
	if (data->peap_version == 0 && data->tlv_request == TLV_REQ_SUCCESS &&
	    data->crypto_binding != NO_BINDING) {
		mlen += 60; /* Cryptobinding TLV */
#ifdef EAP_SERVER_TNC
		if (data->soh_response)
			mlen += wpabuf_len(data->soh_response);
#endif /* EAP_SERVER_TNC */
	}

	buf = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, mlen,
			    EAP_CODE_REQUEST, id);
	if (buf == NULL)
		return NULL;

	wpabuf_put_u8(buf, 0x80); /* Mandatory */
	wpabuf_put_u8(buf, EAP_TLV_RESULT_TLV);
	/* Length */
	wpabuf_put_be16(buf, 2);
	/* Status */
	wpabuf_put_be16(buf, data->tlv_request == TLV_REQ_SUCCESS ?
			EAP_TLV_RESULT_SUCCESS : EAP_TLV_RESULT_FAILURE);

	if (data->peap_version == 0 && data->tlv_request == TLV_REQ_SUCCESS &&
	    data->crypto_binding != NO_BINDING) {
		u8 *mac;
		u8 eap_type = EAP_TYPE_PEAP;
		const u8 *addr[2];
		size_t len[2];
		u16 tlv_type;

#ifdef EAP_SERVER_TNC
		if (data->soh_response) {
			wpa_printf(MSG_DEBUG, "EAP-PEAP: Adding MS-SOH "
				   "Response TLV");
			wpabuf_put_buf(buf, data->soh_response);
			wpabuf_free(data->soh_response);
			data->soh_response = NULL;
		}
#endif /* EAP_SERVER_TNC */

		if (eap_peap_derive_cmk(sm, data) < 0 ||
		    random_get_bytes(data->binding_nonce, 32)) {
			wpabuf_free(buf);
			return NULL;
		}

		/* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */
		addr[0] = wpabuf_put(buf, 0);
		len[0] = 60;
		addr[1] = &eap_type;
		len[1] = 1;

		tlv_type = EAP_TLV_CRYPTO_BINDING_TLV;
		wpabuf_put_be16(buf, tlv_type);
		wpabuf_put_be16(buf, 56);

		wpabuf_put_u8(buf, 0); /* Reserved */
		wpabuf_put_u8(buf, data->peap_version); /* Version */
		wpabuf_put_u8(buf, data->recv_version); /* RecvVersion */
		wpabuf_put_u8(buf, 0); /* SubType: 0 = Request, 1 = Response */
		wpabuf_put_data(buf, data->binding_nonce, 32); /* Nonce */
		mac = wpabuf_put(buf, 20); /* Compound_MAC */
		wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC CMK",
			    data->cmk, 20);
		wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 1",
			    addr[0], len[0]);
		wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 2",
			    addr[1], len[1]);
		hmac_sha1_vector(data->cmk, 20, 2, addr, len, mac);
		wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC",
			    mac, SHA1_MAC_LEN);
		data->crypto_binding_sent = 1;
	}

	wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 TLV data",
			    buf);

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

	return encr_req;
}
Beispiel #22
0
static void
eap_pwd_perform_id_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
			    struct eap_method_ret *ret,
			    const struct wpabuf *reqData,
			    const u8 *payload, size_t payload_len)
{
	struct eap_pwd_id *id;
	const u8 *password;
	size_t password_len;
	u8 pwhashhash[16];
	int res;

	if (data->state != PWD_ID_Req) {
		ret->ignore = TRUE;
		eap_pwd_state(data, FAILURE);
		return;
	}

	if (payload_len < sizeof(struct eap_pwd_id)) {
		ret->ignore = TRUE;
		eap_pwd_state(data, FAILURE);
		return;
	}

	id = (struct eap_pwd_id *) payload;
	data->group_num = be_to_host16(id->group_num);
	wpa_printf(MSG_DEBUG,
		   "EAP-PWD: Server EAP-pwd-ID proposal: group=%u random=%u prf=%u prep=%u",
		   data->group_num, id->random_function, id->prf, id->prep);
	if ((id->random_function != EAP_PWD_DEFAULT_RAND_FUNC) ||
	    (id->prf != EAP_PWD_DEFAULT_PRF)) {
		ret->ignore = TRUE;
		eap_pwd_state(data, FAILURE);
		return;
	}

	if (id->prep != EAP_PWD_PREP_NONE &&
	    id->prep != EAP_PWD_PREP_MS) {
		wpa_printf(MSG_DEBUG,
			   "EAP-PWD: Unsupported password pre-processing technique (Prep=%u)",
			   id->prep);
		eap_pwd_state(data, FAILURE);
		return;
	}

	if (id->prep == EAP_PWD_PREP_NONE && data->password_hash) {
		wpa_printf(MSG_DEBUG,
			   "EAP-PWD: Unhashed password not available");
		eap_pwd_state(data, FAILURE);
		return;
	}

	wpa_printf(MSG_DEBUG, "EAP-PWD (peer): using group %d",
		   data->group_num);

	data->id_server = os_malloc(payload_len - sizeof(struct eap_pwd_id));
	if (data->id_server == NULL) {
		wpa_printf(MSG_INFO, "EAP-PWD: memory allocation id fail");
		eap_pwd_state(data, FAILURE);
		return;
	}
	data->id_server_len = payload_len - sizeof(struct eap_pwd_id);
	os_memcpy(data->id_server, id->identity, data->id_server_len);
	wpa_hexdump_ascii(MSG_INFO, "EAP-PWD (peer): server sent id of",
			  data->id_server, data->id_server_len);

	data->grp = os_zalloc(sizeof(EAP_PWD_group));
	if (data->grp == NULL) {
		wpa_printf(MSG_INFO, "EAP-PWD: failed to allocate memory for "
			   "group");
		eap_pwd_state(data, FAILURE);
		return;
	}

	if (id->prep == EAP_PWD_PREP_MS) {
		if (data->password_hash) {
			res = hash_nt_password_hash(data->password, pwhashhash);
		} else {
			u8 pwhash[16];

			res = nt_password_hash(data->password,
					       data->password_len, pwhash);
			if (res == 0)
				res = hash_nt_password_hash(pwhash, pwhashhash);
			os_memset(pwhash, 0, sizeof(pwhash));
		}

		if (res) {
			eap_pwd_state(data, FAILURE);
			return;
		}

		password = pwhashhash;
		password_len = sizeof(pwhashhash);
	} else {
		password = data->password;
		password_len = data->password_len;
	}

	/* compute PWE */
	res = compute_password_element(data->grp, data->group_num,
				       password, password_len,
				       data->id_server, data->id_server_len,
				       data->id_peer, data->id_peer_len,
				       id->token);
	os_memset(pwhashhash, 0, sizeof(pwhashhash));
	if (res) {
		wpa_printf(MSG_INFO, "EAP-PWD (peer): unable to compute PWE");
		eap_pwd_state(data, FAILURE);
		return;
	}

	wpa_printf(MSG_DEBUG, "EAP-PWD (peer): computed %d bit PWE...",
		   BN_num_bits(data->grp->prime));

	data->outbuf = wpabuf_alloc(sizeof(struct eap_pwd_id) +
				    data->id_peer_len);
	if (data->outbuf == NULL) {
		eap_pwd_state(data, FAILURE);
		return;
	}
	wpabuf_put_be16(data->outbuf, data->group_num);
	wpabuf_put_u8(data->outbuf, EAP_PWD_DEFAULT_RAND_FUNC);
	wpabuf_put_u8(data->outbuf, EAP_PWD_DEFAULT_PRF);
	wpabuf_put_data(data->outbuf, id->token, sizeof(id->token));
	wpabuf_put_u8(data->outbuf, EAP_PWD_PREP_NONE);
	wpabuf_put_data(data->outbuf, data->id_peer, data->id_peer_len);

	eap_pwd_state(data, PWD_Commit_Req);
}
int wps_build_wfa_ext(struct wpabuf *msg, int req_to_enroll,
		      const u8 *auth_macs, size_t auth_macs_count,
		      u8 multi_ap_subelem)
{
	u8 *len;

#ifdef CONFIG_WPS_TESTING
	if (WPS_VERSION == 0x10)
		return 0;
#endif /* CONFIG_WPS_TESTING */

	if (wpabuf_tailroom(msg) <
	    7 + 3 + (req_to_enroll ? 3 : 0) +
	    (auth_macs ? 2 + auth_macs_count * ETH_ALEN : 0))
		return -1;
	wpabuf_put_be16(msg, ATTR_VENDOR_EXT);
	len = wpabuf_put(msg, 2); /* to be filled */
	wpabuf_put_be24(msg, WPS_VENDOR_ID_WFA);

	wpa_printf(MSG_DEBUG, "WPS:  * Version2 (0x%x)", WPS_VERSION);
	wpabuf_put_u8(msg, WFA_ELEM_VERSION2);
	wpabuf_put_u8(msg, 1);
	wpabuf_put_u8(msg, WPS_VERSION);

	if (req_to_enroll) {
		wpa_printf(MSG_DEBUG, "WPS:  * Request to Enroll (1)");
		wpabuf_put_u8(msg, WFA_ELEM_REQUEST_TO_ENROLL);
		wpabuf_put_u8(msg, 1);
		wpabuf_put_u8(msg, 1);
	}

	if (auth_macs && auth_macs_count) {
		size_t i;
		wpa_printf(MSG_DEBUG, "WPS:  * AuthorizedMACs (count=%d)",
			   (int) auth_macs_count);
		wpabuf_put_u8(msg, WFA_ELEM_AUTHORIZEDMACS);
		wpabuf_put_u8(msg, auth_macs_count * ETH_ALEN);
		wpabuf_put_data(msg, auth_macs, auth_macs_count * ETH_ALEN);
		for (i = 0; i < auth_macs_count; i++)
			wpa_printf(MSG_DEBUG, "WPS:    AuthorizedMAC: " MACSTR,
				   MAC2STR(&auth_macs[i * ETH_ALEN]));
	}

	if (multi_ap_subelem) {
		wpa_printf(MSG_DEBUG, "WPS:  * Multi-AP (0x%x)",
			   multi_ap_subelem);
		wpabuf_put_u8(msg, WFA_ELEM_MULTI_AP);
		wpabuf_put_u8(msg, 1); /* length */
		wpabuf_put_u8(msg, multi_ap_subelem);
	}

	WPA_PUT_BE16(len, (u8 *) wpabuf_put(msg, 0) - len - 2);

#ifdef CONFIG_WPS_TESTING
	if (WPS_VERSION > 0x20) {
		if (wpabuf_tailroom(msg) < 5)
			return -1;
		wpa_printf(MSG_DEBUG, "WPS:  * Extensibility Testing - extra "
			   "attribute");
		wpabuf_put_be16(msg, ATTR_EXTENSIBILITY_TEST);
		wpabuf_put_be16(msg, 1);
		wpabuf_put_u8(msg, 42);
	}
#endif /* CONFIG_WPS_TESTING */
	return 0;
}
static void
eap_pwd_perform_id_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
			    struct eap_method_ret *ret,
			    const struct wpabuf *reqData,
			    const u8 *payload, size_t payload_len)
{
	struct eap_pwd_id *id;

	if (data->state != PWD_ID_Req) {
		ret->ignore = TRUE;
		eap_pwd_state(data, FAILURE);
		return;
	}

	if (payload_len < sizeof(struct eap_pwd_id)) {
		ret->ignore = TRUE;
		eap_pwd_state(data, FAILURE);
		return;
	}

	id = (struct eap_pwd_id *) payload;
	data->group_num = be_to_host16(id->group_num);
	if ((id->random_function != EAP_PWD_DEFAULT_RAND_FUNC) ||
	    (id->prf != EAP_PWD_DEFAULT_PRF)) {
		ret->ignore = TRUE;
		eap_pwd_state(data, FAILURE);
		return;
	}

	wpa_printf(MSG_DEBUG, "EAP-PWD (peer): using group %d",
		   data->group_num);

	data->id_server = os_malloc(payload_len - sizeof(struct eap_pwd_id));
	if (data->id_server == NULL) {
		wpa_printf(MSG_INFO, "EAP-PWD: memory allocation id fail");
		eap_pwd_state(data, FAILURE);
		return;
	}
	data->id_server_len = payload_len - sizeof(struct eap_pwd_id);
	os_memcpy(data->id_server, id->identity, data->id_server_len);
	wpa_hexdump_ascii(MSG_INFO, "EAP-PWD (peer): server sent id of",
			  data->id_server, data->id_server_len);

	if ((data->grp = (EAP_PWD_group *) os_malloc(sizeof(EAP_PWD_group))) ==
	    NULL) {
		wpa_printf(MSG_INFO, "EAP-PWD: failed to allocate memory for "
			   "group");
		eap_pwd_state(data, FAILURE);
		return;
	}

	/* compute PWE */
	if (compute_password_element(data->grp, data->group_num,
				     data->password, data->password_len,
				     data->id_server, data->id_server_len,
				     data->id_peer, data->id_peer_len,
				     id->token)) {
		wpa_printf(MSG_INFO, "EAP-PWD (peer): unable to compute PWE");
		eap_pwd_state(data, FAILURE);
		return;
	}

	wpa_printf(MSG_DEBUG, "EAP-PWD (peer): computed %d bit PWE...",
		   BN_num_bits(data->grp->prime));

	data->outbuf = wpabuf_alloc(sizeof(struct eap_pwd_id) +
				    data->id_peer_len);
	if (data->outbuf == NULL) {
		eap_pwd_state(data, FAILURE);
		return;
	}
	wpabuf_put_be16(data->outbuf, data->group_num);
	wpabuf_put_u8(data->outbuf, EAP_PWD_DEFAULT_RAND_FUNC);
	wpabuf_put_u8(data->outbuf, EAP_PWD_DEFAULT_PRF);
	wpabuf_put_data(data->outbuf, id->token, sizeof(id->token));
	wpabuf_put_u8(data->outbuf, EAP_PWD_PREP_NONE);
	wpabuf_put_data(data->outbuf, data->id_peer, data->id_peer_len);

	eap_pwd_state(data, PWD_Commit_Req);
}
Beispiel #25
0
static struct wpabuf * eap_pax_process_std_1(struct eap_pax_data *data,
					     struct eap_method_ret *ret, u8 id,
					     const struct eap_pax_hdr *req,
					     size_t req_plen)
{
	struct wpabuf *resp;
	const u8 *pos;
	u8 *rpos;
	size_t left, plen;

	wpa_printf(MSG_DEBUG, "EAP-PAX: PAX_STD-1 (received)");

	if (data->state != PAX_INIT) {
		wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-1 received in "
			   "unexpected state (%d) - ignored", data->state);
		ret->ignore = TRUE;
		return NULL;
	}

	if (req->flags & EAP_PAX_FLAGS_CE) {
		wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-1 with CE flag set - "
			   "ignored");
		ret->ignore = TRUE;
		return NULL;
	}

	left = req_plen - sizeof(*req);

	if (left < 2 + EAP_PAX_RAND_LEN) {
		wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-1 with too short "
			   "payload");
		ret->ignore = TRUE;
		return NULL;
	}

	pos = (const u8 *) (req + 1);
	if (WPA_GET_BE16(pos) != EAP_PAX_RAND_LEN) {
		wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-1 with incorrect A "
			   "length %d (expected %d)",
			   WPA_GET_BE16(pos), EAP_PAX_RAND_LEN);
		ret->ignore = TRUE;
		return NULL;
	}

	pos += 2;
	left -= 2;
	os_memcpy(data->rand.r.x, pos, EAP_PAX_RAND_LEN);
	wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: X (server rand)",
		    data->rand.r.x, EAP_PAX_RAND_LEN);
	pos += EAP_PAX_RAND_LEN;
	left -= EAP_PAX_RAND_LEN;

	if (left > 0) {
		wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ignored extra payload",
			    pos, left);
	}

	if (random_get_bytes(data->rand.r.y, EAP_PAX_RAND_LEN)) {
		wpa_printf(MSG_ERROR, "EAP-PAX: Failed to get random data");
		ret->ignore = TRUE;
		return NULL;
	}
	wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Y (client rand)",
		    data->rand.r.y, EAP_PAX_RAND_LEN);

	if (eap_pax_initial_key_derivation(req->mac_id, data->ak, data->rand.e,
					   data->mk, data->ck, data->ick,
					   data->mid) < 0) {
		ret->ignore = TRUE;
		return NULL;
	}

	wpa_printf(MSG_DEBUG, "EAP-PAX: PAX_STD-2 (sending)");

	plen = 2 + EAP_PAX_RAND_LEN + 2 + data->cid_len + 2 + EAP_PAX_MAC_LEN +
		EAP_PAX_ICV_LEN;
	resp = eap_pax_alloc_resp(req, id, EAP_PAX_OP_STD_2, plen);
	if (resp == NULL)
		return NULL;

	wpabuf_put_be16(resp, EAP_PAX_RAND_LEN);
	wpabuf_put_data(resp, data->rand.r.y, EAP_PAX_RAND_LEN);
	wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: B = Y (client rand)",
		    data->rand.r.y, EAP_PAX_RAND_LEN);

	wpabuf_put_be16(resp, data->cid_len);
	wpabuf_put_data(resp, data->cid, data->cid_len);
	wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-PAX: CID",
			  (u8 *) data->cid, data->cid_len);

	wpabuf_put_be16(resp, EAP_PAX_MAC_LEN);
	rpos = wpabuf_put(resp, EAP_PAX_MAC_LEN);
	eap_pax_mac(req->mac_id, data->ck, EAP_PAX_CK_LEN,
		    data->rand.r.x, EAP_PAX_RAND_LEN,
		    data->rand.r.y, EAP_PAX_RAND_LEN,
		    (u8 *) data->cid, data->cid_len, rpos);
	wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: MAC_CK(A, B, CID)",
		    rpos, EAP_PAX_MAC_LEN);

	/* Optional ADE could be added here, if needed */

	rpos = wpabuf_put(resp, EAP_PAX_ICV_LEN);
	eap_pax_mac(req->mac_id, data->ick, EAP_PAX_ICK_LEN,
		    wpabuf_head(resp), wpabuf_len(resp) - EAP_PAX_ICV_LEN,
		    NULL, 0, NULL, 0, rpos);
	wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", rpos, EAP_PAX_ICV_LEN);

	data->state = PAX_STD_2_SENT;
	data->mac_id = req->mac_id;
	data->dh_group_id = req->dh_group_id;
	data->public_key_id = req->public_key_id;

	return resp;
}
Beispiel #26
0
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);
}
Beispiel #27
0
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);
}