Beispiel #1
0
static struct wpabuf * ndef_build_record(u8 flags, void *type,
					 u8 type_length, void *id,
					 u8 id_length, void *payload,
					 u32 payload_length)
{
	struct wpabuf *record;
	size_t total_len;
	int short_record;
	u8 local_flag;

	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_data(record, payload, payload_length);
	return record;
}
Beispiel #2
0
static struct wpabuf * eap_tlv_build_nak(int id, u16 nak_type)
{
	struct wpabuf *msg;

	msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, 10,
			    EAP_CODE_RESPONSE, id);
	if (msg == NULL)
		return NULL;

	wpabuf_put_u8(msg, 0x80); /* Mandatory */
	wpabuf_put_u8(msg, EAP_TLV_NAK_TLV);
	wpabuf_put_be16(msg, 6); /* Length */
	wpabuf_put_be32(msg, 0); /* Vendor-Id */
	wpabuf_put_be16(msg, nak_type); /* NAK-Type */

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

	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 * p2p_build_sd_query(u16 update_indic,
					  struct wpabuf *tlvs)
{
	struct wpabuf *buf;
	u8 *len_pos;

	buf = gas_anqp_build_initial_req(0, 100 + wpabuf_len(tlvs));
	if (buf == NULL)
		return NULL;

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

	gas_anqp_set_len(buf);

	return buf;
}
Beispiel #5
0
static struct wpabuf * eap_eke_build_fail(struct eap_eke_data *data,
					  struct eap_method_ret *ret,
					  u8 id, u32 failure_code)
{
	struct wpabuf *resp;

	wpa_printf(MSG_DEBUG, "EAP-EKE: Sending EAP-EKE-Failure/Response - code=0x%x",
		   failure_code);

	resp = eap_eke_build_msg(data, id, 4, EAP_EKE_FAILURE);
	if (resp)
		wpabuf_put_be32(resp, failure_code);

	os_memset(data->dh_priv, 0, sizeof(data->dh_priv));
	eap_eke_session_clean(&data->sess);

	eap_eke_state(data, FAILURE);
	ret->methodState = METHOD_DONE;
	ret->decision = DECISION_FAIL;
	ret->allowNotifications = FALSE;

	return resp;
}
Beispiel #6
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;
}
Beispiel #7
0
/**
 * 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;
}
Beispiel #8
0
/**
 * 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;
}
Beispiel #9
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);
}
static struct wpabuf * eap_ikev2_build_msg(struct eap_ikev2_data *data, u8 id)
{
	struct wpabuf *req;
	u8 flags;
	size_t send_len, plen, icv_len = 0;

	wpa_printf(MSG_DEBUG, "EAP-IKEV2: Generating Request");

	flags = 0;
	send_len = wpabuf_len(data->out_buf) - data->out_used;
	if (1 + send_len > data->fragment_size) {
		send_len = data->fragment_size - 1;
		flags |= IKEV2_FLAGS_MORE_FRAGMENTS;
		if (data->out_used == 0) {
			flags |= IKEV2_FLAGS_LENGTH_INCLUDED;
			send_len -= 4;
		}
	}

	plen = 1 + send_len;
	if (flags & IKEV2_FLAGS_LENGTH_INCLUDED)
		plen += 4;
	if (data->keys_ready) {
		const struct ikev2_integ_alg *integ;
		wpa_printf(MSG_DEBUG, "EAP-IKEV2: Add Integrity Checksum "
			   "Data");
		flags |= IKEV2_FLAGS_ICV_INCLUDED;
		integ = ikev2_get_integ(data->ikev2.proposal.integ);
		if (integ == NULL) {
			wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unknown INTEG "
				   "transform / cannot generate ICV");
			return NULL;
		}
		icv_len = integ->hash_len;

		plen += icv_len;
	}
	req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, plen,
			    EAP_CODE_REQUEST, id);
	if (req == NULL)
		return NULL;

	wpabuf_put_u8(req, flags); /* Flags */
	if (flags & IKEV2_FLAGS_LENGTH_INCLUDED)
		wpabuf_put_be32(req, wpabuf_len(data->out_buf));

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

	if (flags & IKEV2_FLAGS_ICV_INCLUDED) {
		const u8 *msg = wpabuf_head(req);
		size_t len = wpabuf_len(req);
		ikev2_integ_hash(data->ikev2.proposal.integ,
				 data->ikev2.keys.SK_ai,
				 data->ikev2.keys.SK_integ_len,
				 msg, len, wpabuf_put(req, icv_len));
	}

	if (data->out_used == wpabuf_len(data->out_buf)) {
		wpa_printf(MSG_DEBUG, "EAP-IKEV2: Sending out %lu bytes "
			   "(message sent completely)",
			   (unsigned long) send_len);
		wpabuf_free(data->out_buf);
		data->out_buf = NULL;
		data->out_used = 0;
	} else {
		wpa_printf(MSG_DEBUG, "EAP-IKEV2: Sending out %lu bytes "
			   "(%lu more to send)", (unsigned long) send_len,
			   (unsigned long) wpabuf_len(data->out_buf) -
			   data->out_used);
		eap_ikev2_state(data, WAIT_FRAG_ACK);
	}

	return req;
}
Beispiel #11
0
static struct wpabuf * eap_ikev2_build_msg(struct eap_ikev2_data *data,
					   struct eap_method_ret *ret, u8 id)
{
	struct wpabuf *resp;
	u8 flags;
	size_t send_len, plen, icv_len = 0;

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

	flags = 0;
	send_len = wpabuf_len(data->out_buf) - data->out_used;
	if (1 + send_len > data->fragment_size) {
		send_len = data->fragment_size - 1;
		flags |= IKEV2_FLAGS_MORE_FRAGMENTS;
		if (data->out_used == 0) {
			flags |= IKEV2_FLAGS_LENGTH_INCLUDED;
			send_len -= 4;
		}
	}
#ifdef CCNS_PL
	/* Some issues figuring out the length of the message if Message Length
	 * field not included?! */
	if (!(flags & IKEV2_FLAGS_LENGTH_INCLUDED))
		flags |= IKEV2_FLAGS_LENGTH_INCLUDED;
#endif /* CCNS_PL */

	plen = 1 + send_len;
	if (flags & IKEV2_FLAGS_LENGTH_INCLUDED)
		plen += 4;
	if (data->keys_ready) {
		const struct ikev2_integ_alg *integ;
		wpa_printf(MSG_DEBUG, "EAP-IKEV2: Add Integrity Checksum "
			   "Data");
		flags |= IKEV2_FLAGS_ICV_INCLUDED;
		integ = ikev2_get_integ(data->ikev2.proposal.integ);
		if (integ == NULL) {
			wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unknown INTEG "
				   "transform / cannot generate ICV");
			return NULL;
		}
		icv_len = integ->hash_len;

		plen += icv_len;
	}
	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, plen,
			     EAP_CODE_RESPONSE, id);
	if (resp == NULL)
		return NULL;

	wpabuf_put_u8(resp, flags); /* Flags */
	if (flags & IKEV2_FLAGS_LENGTH_INCLUDED)
		wpabuf_put_be32(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;

	if (flags & IKEV2_FLAGS_ICV_INCLUDED) {
		const u8 *msg = wpabuf_head(resp);
		size_t len = wpabuf_len(resp);
		ikev2_integ_hash(data->ikev2.proposal.integ,
				 data->ikev2.keys.SK_ar,
				 data->ikev2.keys.SK_integ_len,
				 msg, len, wpabuf_put(resp, icv_len));
	}

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

	if (data->out_used == wpabuf_len(data->out_buf)) {
		wpa_printf(MSG_DEBUG, "EAP-IKEV2: Sending out %lu bytes "
			   "(message sent completely)",
			   (unsigned long) send_len);
		wpabuf_free(data->out_buf);
		data->out_buf = NULL;
		data->out_used = 0;
		switch (data->ikev2.state) {
		case SA_AUTH:
			/* SA_INIT was sent out, so message have to be
			 * integrity protected from now on. */
			data->keys_ready = 1;
			break;
		case IKEV2_DONE:
			ret->methodState = METHOD_DONE;
			if (data->state == FAIL)
				break;
			ret->decision = DECISION_COND_SUCC;
			wpa_printf(MSG_DEBUG, "EAP-IKEV2: Authentication "
				   "completed successfully");
			if (eap_ikev2_peer_keymat(data))
				break;
			eap_ikev2_state(data, DONE);
			break;
		case IKEV2_FAILED:
			wpa_printf(MSG_DEBUG, "EAP-IKEV2: Authentication "
				   "failed");
			ret->methodState = METHOD_DONE;
			ret->decision = DECISION_FAIL;
			break;
		default:
			break;
		}
	} else {
		wpa_printf(MSG_DEBUG, "EAP-IKEV2: Sending out %lu bytes "
			   "(%lu more to send)", (unsigned long) send_len,
			   (unsigned long) wpabuf_len(data->out_buf) -
			   data->out_used);
		eap_ikev2_state(data, WAIT_FRAG_ACK);
	}

	return resp;
}
Beispiel #12
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;
}
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 #14
0
/**
 * eap_tls_process_output - Process outgoing TLS message
 * @data: Data for TLS processing
 * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...)
 * @peap_version: Version number for EAP-PEAP/TTLS
 * @id: EAP identifier for the response
 * @ret: Return value to use on success
 * @out_data: Buffer for returning the allocated output buffer
 * Returns: ret (0 or 1) on success, -1 on failure
 */
static int eap_tls_process_output(struct eap_ssl_data *data, EapType eap_type,
				  int peap_version, u8 id, int ret,
				  struct wpabuf **out_data)
{
	size_t len;
	u8 *flags;
	int more_fragments, length_included;

	if (data->tls_out == NULL)
		return -1;
	len = wpabuf_len(data->tls_out) - data->tls_out_pos;
	wpa_printf(MSG_DEBUG, "SSL: %lu bytes left to be sent out (of total "
		   "%lu bytes)",
		   (unsigned long) len,
		   (unsigned long) wpabuf_len(data->tls_out));

	/*
	 * Limit outgoing message to the configured maximum size. Fragment
	 * message if needed.
	 */
	if (len > data->tls_out_limit) {
		more_fragments = 1;
		len = data->tls_out_limit;
		wpa_printf(MSG_DEBUG, "SSL: sending %lu bytes, more fragments "
			   "will follow", (unsigned long) len);
	} else
		more_fragments = 0;

	length_included = data->tls_out_pos == 0 &&
		(wpabuf_len(data->tls_out) > data->tls_out_limit ||
		 data->include_tls_length);
	if (!length_included &&
	    eap_type == EAP_TYPE_PEAP && peap_version == 0 &&
	    !tls_connection_established(data->eap->ssl_ctx, data->conn)) {
		/*
		 * Windows Server 2008 NPS really wants to have the TLS Message
		 * length included in phase 0 even for unfragmented frames or
		 * it will get very confused with Compound MAC calculation and
		 * Outer TLVs.
		 */
		length_included = 1;
	}

	*out_data = eap_tls_msg_alloc(eap_type, 1 + length_included * 4 + len,
				      EAP_CODE_RESPONSE, id);
	if (*out_data == NULL)
		return -1;

	flags = wpabuf_put(*out_data, 1);
	*flags = peap_version;
	if (more_fragments)
		*flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS;
	if (length_included) {
		*flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED;
		wpabuf_put_be32(*out_data, wpabuf_len(data->tls_out));
	}

	wpabuf_put_data(*out_data,
			wpabuf_head_u8(data->tls_out) + data->tls_out_pos,
			len);
	data->tls_out_pos += len;

	if (!more_fragments)
		eap_peer_tls_reset_output(data);

	return ret;
}
Beispiel #15
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;
}