コード例 #1
0
ファイル: wnm_sta.c プロジェクト: gxk/hostap
static int wnm_add_nei_rep(u8 *buf, size_t len, const u8 *bssid, u32 bss_info,
			   u8 op_class, u8 chan, u8 phy_type, u8 pref)
{
	u8 *pos = buf;

	if (len < 18) {
		wpa_printf(MSG_DEBUG,
			   "WNM: Not enough room for Neighbor Report element");
		return -1;
	}

	*pos++ = WLAN_EID_NEIGHBOR_REPORT;
	/* length: 13 for basic neighbor report + 3 for preference subelement */
	*pos++ = 16;
	os_memcpy(pos, bssid, ETH_ALEN);
	pos += ETH_ALEN;
	WPA_PUT_LE32(pos, bss_info);
	pos += 4;
	*pos++ = op_class;
	*pos++ = chan;
	*pos++ = phy_type;
	*pos++ = WNM_NEIGHBOR_BSS_TRANSITION_CANDIDATE;
	*pos++ = 1;
	*pos++ = pref;
	return pos - buf;
}
コード例 #2
0
static void wpa_ft_generate_pmk_r1(struct wpa_authenticator *wpa_auth,
				   struct wpa_ft_pmk_r0_sa *pmk_r0,
				   struct ft_remote_r1kh *r1kh,
				   const u8 *s1kh_id, int pairwise)
{
	struct ft_r0kh_r1kh_push_frame frame, f;
	struct os_time now;

	os_memset(&frame, 0, sizeof(frame));
	frame.frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB;
	frame.packet_type = FT_PACKET_R0KH_R1KH_PUSH;
	frame.data_length = host_to_le16(FT_R0KH_R1KH_PUSH_DATA_LEN);
	os_memcpy(frame.ap_address, wpa_auth->addr, ETH_ALEN);

	/* aes_wrap() does not support inplace encryption, so use a temporary
	 * buffer for the data. */
	os_memcpy(f.r1kh_id, r1kh->id, FT_R1KH_ID_LEN);
	os_memcpy(f.s1kh_id, s1kh_id, ETH_ALEN);
	os_memcpy(f.pmk_r0_name, pmk_r0->pmk_r0_name, WPA_PMK_NAME_LEN);
	wpa_derive_pmk_r1(pmk_r0->pmk_r0, pmk_r0->pmk_r0_name, r1kh->id,
			  s1kh_id, f.pmk_r1, f.pmk_r1_name);
	wpa_printf(MSG_DEBUG, "FT: R1KH-ID " MACSTR, MAC2STR(r1kh->id));
	wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", f.pmk_r1, PMK_LEN);
	wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", f.pmk_r1_name,
		    WPA_PMK_NAME_LEN);
	os_get_time(&now);
	WPA_PUT_LE32(f.timestamp, now.sec);
	f.pairwise = host_to_le16(pairwise);
	if (aes_wrap(r1kh->key, (FT_R0KH_R1KH_PUSH_DATA_LEN + 7) / 8,
		     f.timestamp, frame.timestamp) < 0)
		return;

	wpa_ft_rrb_send(wpa_auth, r1kh->addr, (u8 *) &frame, sizeof(frame));
}
コード例 #3
0
static void test_vector_ccmp(void)
{
	u8 tk[] = { 0xc9, 0x7c, 0x1f, 0x67, 0xce, 0x37, 0x11, 0x85,
		    0x51, 0x4a, 0x8a, 0x19, 0xf2, 0xbd, 0xd5, 0x2f };
	u8 pn[] = { 0xB5, 0x03, 0x97, 0x76, 0xE7, 0x0C };
	u8 frame[] = {
		0x08, 0x48, 0xc3, 0x2c, 0x0f, 0xd2, 0xe1, 0x28,
		0xa5, 0x7c, 0x50, 0x30, 0xf1, 0x84, 0x44, 0x08,
		0xab, 0xae, 0xa5, 0xb8, 0xfc, 0xba, 0x80, 0x33,
		0xf8, 0xba, 0x1a, 0x55, 0xd0, 0x2f, 0x85, 0xae,
		0x96, 0x7b, 0xb6, 0x2f, 0xb6, 0xcd, 0xa8, 0xeb,
		0x7e, 0x78, 0xa0, 0x50
	};
	u8 *enc, *plain;
	size_t enc_len, plain_len;
	u8 fcs[4];

	wpa_printf(MSG_INFO, "\nIEEE Std 802.11-2012, M.6.4 CCMP test "
		   "vector\n");

	wpa_hexdump(MSG_INFO, "TK", tk, sizeof(tk));
	wpa_hexdump(MSG_INFO, "PN", pn, sizeof(pn));
	wpa_hexdump(MSG_INFO, "802.11 Header", frame, 24);
	wpa_hexdump(MSG_INFO, "Plaintext Data", frame + 24, sizeof(frame) - 24);

	enc = ccmp_encrypt(tk, frame, sizeof(frame), 24, NULL, pn, 0, &enc_len);
	if (enc == NULL) {
		wpa_printf(MSG_ERROR, "Failed to encrypt CCMP frame");
		return;
	}

	wpa_hexdump(MSG_INFO, "Encrypted MPDU (without FCS)", enc, enc_len);
	WPA_PUT_LE32(fcs, crc32(enc, enc_len));
	wpa_hexdump(MSG_INFO, "FCS", fcs, sizeof(fcs));

	wpa_debug_level = MSG_INFO;
	plain = ccmp_decrypt(tk, (const struct ieee80211_hdr *) enc,
			     enc + 24, enc_len - 24, &plain_len);
	wpa_debug_level = MSG_EXCESSIVE;
	os_free(enc);

	if (plain == NULL) {
		wpa_printf(MSG_ERROR, "Failed to decrypt CCMP frame");
		return;
	}

	if (plain_len != sizeof(frame) - 24 ||
	    os_memcmp(plain, frame + 24, plain_len) != 0) {
		wpa_hexdump(MSG_ERROR, "Decryption result did not match",
			    plain, plain_len);
	}

	os_free(plain);
}
コード例 #4
0
ファイル: ccx_cckm.c プロジェクト: pocketbook/801
/**
 * wpa_btk_to_ptk - Calculate PTK from BTK, address, and Replay Counter
 * @btk: Base Transient Key
 * @btk_len: Length of BTK
 * @bssid: BSSID / AP ID
 * @ptk: Buffer for Pairwise Transient Key
 * @ptk_len: Length of PTK
 *
 * PTK = PRF-512(BTK, "", RN || AP_ID)
 */
void wpa_btk_to_ptk(const u8 *btk, size_t btk_len, const u8 *bssid,
		u32 cckm_rn, u8 *ptk, size_t ptk_len)
{
	u8 data[ETH_ALEN + 4];

	WPA_PUT_LE32(data, cckm_rn);
	os_memcpy(data + 4, bssid, ETH_ALEN);

	sha1_prf(btk, btk_len, NULL, data, sizeof(data), ptk, ptk_len);
	wpa_hexdump_key(MSG_DEBUG, "WPA: BTK-PTK", ptk, ptk_len);
}
コード例 #5
0
ファイル: ccx_cckm.c プロジェクト: pocketbook/801
int cckm_build_request (struct wpa_sm *sm, u8 *bssid, u64 timestamp)
{
	struct cckm_ie_req *cie;
	u8 data[128];
	u32 data_len = ETH_ALEN;

	if (sm->cckm_req_ie) {
		os_free(sm->cckm_req_ie);
	}
	sm->cckm_req_ie = os_malloc(32);
	if (sm->cckm_req_ie == NULL)
		return -1;
	cie = (struct cckm_ie_req *)sm->cckm_req_ie;

	os_memcpy(data, sm->own_addr, ETH_ALEN);
	os_memcpy(data+data_len, bssid, ETH_ALEN);
	data_len += ETH_ALEN;

	if (sm->connect_wpa_ie && sm->connect_wpa_ie_len) {
		os_memcpy(data + data_len, sm->connect_wpa_ie,
				sm->connect_wpa_ie_len);
		data_len += sm->connect_wpa_ie_len;
	}

	sm->cckm_rn++;
	cie->elem_id = WLAN_EID_CCKM;
	cie->len = 24;
	os_memcpy(cie->oui, aironet_oui, sizeof(aironet_oui));
	WPA_PUT_LE64(cie->timestamp, timestamp);
	WPA_PUT_LE32(cie->rn, sm->cckm_rn);

	os_memcpy(data+data_len, cie->timestamp, 8);
	data_len += 8;
	os_memcpy(data+data_len, cie->rn, 4);
	data_len += 4;

	if (sm->proto == WPA_PROTO_RSN) {
		hmac_sha1(sm->cgk.krk, CCKM_KRK_LEN, data, data_len,
				cie->mn_mic);
	} else {
		hmac_md5(sm->cgk.krk, CCKM_KRK_LEN, data, data_len,
				cie->mn_mic);
	}

	sm->cckm_req_ie_len = sizeof(struct cckm_ie_req);

	wpa_hexdump(MSG_DEBUG, "req data ", data, data_len);
	wpa_hexdump(MSG_DEBUG, "cckm_req ", sm->cckm_req_ie,
			sm->cckm_req_ie_len);

	wpa_sm_update_cckm_ies(sm, sm->cckm_req_ie, sm->cckm_req_ie_len);
	return 0;
}
コード例 #6
0
ファイル: ieee802_11_shared.c プロジェクト: Adrellias/mana
u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd,
				     struct sta_info *sta, u8 *eid)
{
	u8 *pos = eid;
	u32 timeout, tu;
	struct os_reltime now, passed;

	*pos++ = WLAN_EID_TIMEOUT_INTERVAL;
	*pos++ = 5;
	*pos++ = WLAN_TIMEOUT_ASSOC_COMEBACK;
	os_get_reltime(&now);
	os_reltime_sub(&now, &sta->sa_query_start, &passed);
	tu = (passed.sec * 1000000 + passed.usec) / 1024;
	if (hapd->conf->assoc_sa_query_max_timeout > tu)
		timeout = hapd->conf->assoc_sa_query_max_timeout - tu;
	else
		timeout = 0;
	if (timeout < hapd->conf->assoc_sa_query_max_timeout)
		timeout++; /* add some extra time for local timers */
	WPA_PUT_LE32(pos, timeout);
	pos += 4;

	return pos;
}
コード例 #7
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;
}
コード例 #8
0
ファイル: ccx_cckm.c プロジェクト: pocketbook/801
/**
 * cckm_egtk_to_gtk - Calculate GTK from Encrypted GTK
 * @cckm_rn: Association Request Numner
 * @gtk: Length of BTK
 * @gtk_len: Length of GTK
 *
 * GTK = RC4(RN | PTK-802.1X-Encrypt-Key, EGTK)
 * GTK = AES-Keywrap(PTK-802.1X-Encrypt-Key, EGTK)
 * - where PTK-802.1X-Encrypt-Key is the key as defined in Section 0
 * - Note that while the IV is not transmitted in the clear, its encrypted
 *   value is included in the EGTK. Thus, the EGTK length shall be the GTK
 *   key length plus 8 octets (e.g. the IV length). More explicitly, if the
 *   broadcast cipher is TKIP, while the GTK is 32 octets, the EGTK shall
 *   be 40 octets; similarly for AESCCMP, the GTK is 16 octets while the
 *   EGTK shall be 24 octets.
 */
static int cckm_install_gtk(struct wpa_sm *sm, u32 cckm_rn, u8 *gtk,
		int gtk_len, int keyidx, const u8 *key_rsc, int key_rsc_len)
{
	u8 gtk_buf[32];
	enum wpa_alg alg;

	switch (sm->group_cipher) {
		case WPA_CIPHER_CCMP:
			alg = WPA_ALG_CCMP;
			break;
		case WPA_CIPHER_TKIP:
			alg = WPA_ALG_TKIP;
			break;
		case WPA_CIPHER_NONE:
			wpa_printf(MSG_DEBUG, "WPA: Pairwise Cipher Suite: "
					"NONE - do not use pairwise keys");
			return 0;
		default:
			wpa_printf(MSG_WARNING, "WPA: Unsupported pairwise cipher %d",
					sm->pairwise_cipher);
			return -1;
	}

	if (sm->group_cipher == WPA_CIPHER_CCMP) {
		gtk_len -= 8;
		if (aes_unwrap(sm->ptk.kek, gtk_len / 8, gtk, gtk_buf)) {
			wpa_printf(MSG_WARNING, "WPA: AES unwrap "
					"failed - could not decrypt GTK");
			return -1;
		}
		gtk = gtk_buf;
	} else if (sm->group_cipher == WPA_CIPHER_TKIP) {
		u8 data[20];

		WPA_PUT_LE32(data, cckm_rn);
		os_memcpy(data + 4, &sm->ptk.kek, sizeof(sm->ptk.kek));
		wpa_hexdump_key(MSG_DEBUG, "EGTK-Data", data, sizeof(data));

		rc4_skip(data, sizeof(data), 256, gtk, gtk_len);

		/* Swap Tx/Rx keys for Michael MIC */
		os_memcpy(gtk_buf, gtk, 16);
		os_memcpy(gtk_buf + 16, gtk + 24, 8);
		os_memcpy(gtk_buf + 24, gtk + 16, 8);
		gtk = gtk_buf;
	}

	wpa_hexdump_key(MSG_DEBUG, "WPA: Group Key", gtk, gtk_len);
	wpa_printf(MSG_DEBUG, "WPA: Installing GTK to the driver "
			"(keyidx=%d tx=%d len=%d).", keyidx, 0, gtk_len);
	wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, key_rsc_len);

	if (wpa_sm_set_key(sm, alg, (u8 *) "\xff\xff\xff\xff\xff\xff",
				keyidx, 0, key_rsc, key_rsc_len,
				gtk, gtk_len) < 0) {
		wpa_printf(MSG_WARNING, "WPA: Failed to set GTK to "
				"the driver.");
		return -1;
	}

	return 0;
}