static int wpa_supplicant_send_2_of_2(struct wpa_sm *sm, const struct wpa_eapol_key *key, int ver, u16 key_info) { size_t rlen; struct wpa_eapol_key *reply; u8 *rbuf; rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, sizeof(*reply), &rlen, (void *) &reply); if (rbuf == NULL) return -1; reply->type = sm->proto == WPA_PROTO_RSN ? EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; key_info &= WPA_KEY_INFO_KEY_INDEX_MASK; key_info |= ver | WPA_KEY_INFO_MIC | WPA_KEY_INFO_SECURE; WPA_PUT_BE16(reply->key_info, key_info); if (sm->proto == WPA_PROTO_RSN) WPA_PUT_BE16(reply->key_length, 0); else os_memcpy(reply->key_length, key->key_length, 2); os_memcpy(reply->replay_counter, key->replay_counter, WPA_REPLAY_COUNTER_LEN); WPA_PUT_BE16(reply->key_data_length, 0); wpa_printf(MSG_DEBUG, "WPA: Sending EAPOL-Key 2/2"); wpa_eapol_key_send(sm, sm->ptk.kck, ver, sm->bssid, ETH_P_EAPOL, rbuf, rlen, reply->key_mic); return 0; }
static int wpa_supplicant_send_smk_error(struct wpa_sm *sm, const u8 *dst, const u8 *peer, u16 mui, u16 error_type, int ver) { size_t rlen; struct wpa_eapol_key *err; struct rsn_error_kde error; u8 *rbuf, *pos; size_t kde_len; u16 key_info; kde_len = 2 + RSN_SELECTOR_LEN + sizeof(error); if (peer) kde_len += 2 + RSN_SELECTOR_LEN + ETH_ALEN; rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, sizeof(*err) + kde_len, &rlen, (void *) &err); if (rbuf == NULL) return -1; err->type = EAPOL_KEY_TYPE_RSN; key_info = ver | WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC | WPA_KEY_INFO_SECURE | WPA_KEY_INFO_ERROR | WPA_KEY_INFO_REQUEST; WPA_PUT_BE16(err->key_info, key_info); WPA_PUT_BE16(err->key_length, 0); os_memcpy(err->replay_counter, sm->request_counter, WPA_REPLAY_COUNTER_LEN); inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN); WPA_PUT_BE16(err->key_data_length, (u16) kde_len); pos = (u8 *) (err + 1); if (peer) { /* Peer MAC Address KDE */ pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN); } /* Error KDE */ error.mui = host_to_be16(mui); error.error_type = host_to_be16(error_type); wpa_add_kde(pos, RSN_KEY_DATA_ERROR, (u8 *) &error, sizeof(error)); if (peer) { wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK Error (peer " MACSTR " mui %d error_type %d)", MAC2STR(peer), mui, error_type); } else { wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK Error " "(mui %d error_type %d)", mui, error_type); } wpa_eapol_key_send(sm, sm->ptk.kck, ver, dst, ETH_P_EAPOL, rbuf, rlen, err->key_mic); return 0; }
static void wpa_supplicant_send_stk_1_of_4(struct wpa_sm *sm, struct wpa_peerkey *peerkey) { size_t mlen; struct wpa_eapol_key *msg; u8 *mbuf; size_t kde_len; u16 key_info, ver; kde_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN; mbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, sizeof(*msg) + kde_len, &mlen, (void *) &msg); if (mbuf == NULL) return; msg->type = EAPOL_KEY_TYPE_RSN; if (peerkey->cipher == WPA_CIPHER_CCMP) ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; else ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; key_info = ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_ACK; WPA_PUT_BE16(msg->key_info, key_info); if (peerkey->cipher == WPA_CIPHER_CCMP) WPA_PUT_BE16(msg->key_length, 16); else WPA_PUT_BE16(msg->key_length, 32); os_memcpy(msg->replay_counter, peerkey->replay_counter, WPA_REPLAY_COUNTER_LEN); inc_byte_array(peerkey->replay_counter, WPA_REPLAY_COUNTER_LEN); WPA_PUT_BE16(msg->key_data_length, kde_len); wpa_add_kde((u8 *) (msg + 1), RSN_KEY_DATA_PMKID, peerkey->smkid, PMKID_LEN); if (random_get_bytes(peerkey->inonce, WPA_NONCE_LEN)) { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "RSN: Failed to get random data for INonce (STK)"); os_free(mbuf); return; } wpa_hexdump(MSG_DEBUG, "RSN: INonce for STK 4-Way Handshake", peerkey->inonce, WPA_NONCE_LEN); os_memcpy(msg->key_nonce, peerkey->inonce, WPA_NONCE_LEN); wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key STK 1/4 to " MACSTR, MAC2STR(peerkey->addr)); wpa_eapol_key_send(sm, NULL, ver, peerkey->addr, ETH_P_EAPOL, mbuf, mlen, NULL); }
static void wpa_supplicant_send_stk_3_of_4(struct wpa_sm *sm, struct wpa_peerkey *peerkey) { size_t mlen; struct wpa_eapol_key *msg; u8 *mbuf, *pos; size_t kde_len; u16 key_info, ver; be32 lifetime; kde_len = peerkey->rsnie_i_len + 2 + RSN_SELECTOR_LEN + sizeof(lifetime); mbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, sizeof(*msg) + kde_len, &mlen, (void *) &msg); if (mbuf == NULL) return; msg->type = EAPOL_KEY_TYPE_RSN; if (peerkey->cipher == WPA_CIPHER_CCMP) ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; else ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; key_info = ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_ACK | WPA_KEY_INFO_MIC | WPA_KEY_INFO_SECURE; WPA_PUT_BE16(msg->key_info, key_info); if (peerkey->cipher == WPA_CIPHER_CCMP) WPA_PUT_BE16(msg->key_length, 16); else WPA_PUT_BE16(msg->key_length, 32); os_memcpy(msg->replay_counter, peerkey->replay_counter, WPA_REPLAY_COUNTER_LEN); inc_byte_array(peerkey->replay_counter, WPA_REPLAY_COUNTER_LEN); WPA_PUT_BE16(msg->key_data_length, kde_len); pos = (u8 *) (msg + 1); pos = wpa_add_ie(pos, peerkey->rsnie_i, peerkey->rsnie_i_len); lifetime = host_to_be32(peerkey->lifetime); wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME, (u8 *) &lifetime, sizeof(lifetime)); os_memcpy(msg->key_nonce, peerkey->inonce, WPA_NONCE_LEN); wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key STK 3/4 to " MACSTR, MAC2STR(peerkey->addr)); wpa_eapol_key_send(sm, peerkey->stk.kck, ver, peerkey->addr, ETH_P_EAPOL, mbuf, mlen, msg->key_mic); }
static int wpa_supplicant_send_smk_m3(struct wpa_sm *sm, const unsigned char *src_addr, const struct wpa_eapol_key *key, int ver, struct wpa_peerkey *peerkey) { size_t rlen; struct wpa_eapol_key *reply; u8 *rbuf, *pos; size_t kde_len; u16 key_info; /* KDEs: Peer RSN IE, Initiator MAC Address, Initiator Nonce */ kde_len = peerkey->rsnie_p_len + 2 + RSN_SELECTOR_LEN + ETH_ALEN + 2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN; rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, sizeof(*reply) + kde_len, &rlen, (void *) &reply); if (rbuf == NULL) return -1; reply->type = EAPOL_KEY_TYPE_RSN; key_info = ver | WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC | WPA_KEY_INFO_SECURE; WPA_PUT_BE16(reply->key_info, key_info); WPA_PUT_BE16(reply->key_length, 0); os_memcpy(reply->replay_counter, key->replay_counter, WPA_REPLAY_COUNTER_LEN); os_memcpy(reply->key_nonce, peerkey->pnonce, WPA_NONCE_LEN); WPA_PUT_BE16(reply->key_data_length, (u16) kde_len); pos = (u8 *) (reply + 1); /* Peer RSN IE */ pos = wpa_add_ie(pos, peerkey->rsnie_p, peerkey->rsnie_p_len); /* Initiator MAC Address KDE */ pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peerkey->addr, ETH_ALEN); /* Initiator Nonce */ wpa_add_kde(pos, RSN_KEY_DATA_NONCE, peerkey->inonce, WPA_NONCE_LEN); wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK M3"); wpa_eapol_key_send(sm, sm->ptk.kck, ver, src_addr, ETH_P_EAPOL, rbuf, rlen, reply->key_mic); return 0; }
/** * wpa_sm_key_request - Send EAPOL-Key Request * @sm: Pointer to WPA state machine data from wpa_sm_init() * @error: Indicate whether this is an Michael MIC error report * @pairwise: 1 = error report for pairwise packet, 0 = for group packet * * Send an EAPOL-Key Request to the current authenticator. This function is * used to request rekeying and it is usually called when a local Michael MIC * failure is detected. */ void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise) { size_t rlen; struct wpa_eapol_key *reply; int key_info, ver; u8 bssid[ETH_ALEN], *rbuf; if (wpa_key_mgmt_ft(sm->key_mgmt) || wpa_key_mgmt_sha256(sm->key_mgmt)) ver = WPA_KEY_INFO_TYPE_AES_128_CMAC; else if (sm->pairwise_cipher == WPA_CIPHER_CCMP) ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; else ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; if (wpa_sm_get_bssid(sm, bssid) < 0) { wpa_printf(MSG_WARNING, "Failed to read BSSID for EAPOL-Key " "request"); return; } rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, sizeof(*reply), &rlen, (void *) &reply); if (rbuf == NULL) return; reply->type = sm->proto == WPA_PROTO_RSN ? EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; key_info = WPA_KEY_INFO_REQUEST | ver; if (sm->ptk_set) key_info |= WPA_KEY_INFO_MIC; if (error) key_info |= WPA_KEY_INFO_ERROR; if (pairwise) key_info |= WPA_KEY_INFO_KEY_TYPE; WPA_PUT_BE16(reply->key_info, key_info); WPA_PUT_BE16(reply->key_length, 0); os_memcpy(reply->replay_counter, sm->request_counter, WPA_REPLAY_COUNTER_LEN); inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN); WPA_PUT_BE16(reply->key_data_length, 0); wpa_printf(MSG_INFO, "WPA: Sending EAPOL-Key Request (error=%d " "pairwise=%d ptk_set=%d len=%lu)", error, pairwise, sm->ptk_set, (unsigned long) rlen); wpa_eapol_key_send(sm, sm->ptk.kck, ver, bssid, ETH_P_EAPOL, rbuf, rlen, key_info & WPA_KEY_INFO_MIC ? reply->key_mic : NULL); }
static int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst, const struct wpa_eapol_key *key, int ver, const u8 *nonce, const u8 *wpa_ie, size_t wpa_ie_len, struct wpa_ptk *ptk) { size_t rlen; struct wpa_eapol_key *reply; u8 *rbuf; if (wpa_ie == NULL) { lwip_log("WPA: No wpa_ie set - cannot generate msg 2/4\n"); return -1; } wpa_hexdump(MSG_DEBUG, "WPA: WPA IE for msg 2/4", wpa_ie, wpa_ie_len); rbuf = wpa_alloc_eapol(IEEE802_1X_TYPE_EAPOL_KEY, NULL, sizeof(*reply) + wpa_ie_len, &rlen, (void *) &reply); if (rbuf == NULL) return -1; reply->type = sm->proto == WPA_PROTO_RSN ? EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; WPA_PUT_BE16(reply->key_info, ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_MIC); if (sm->proto == WPA_PROTO_RSN) WPA_PUT_BE16(reply->key_length, 0); else os_memcpy(reply->key_length, key->key_length, 2); os_memcpy(reply->replay_counter, key->replay_counter, WPA_REPLAY_COUNTER_LEN); WPA_PUT_BE16(reply->key_data_length, wpa_ie_len); os_memcpy(reply + 1, wpa_ie, wpa_ie_len); os_memcpy(reply->key_nonce, nonce, WPA_NONCE_LEN); wpa_eapol_key_send(sm, ptk->kck, ver, dst, ETH_P_EAPOL, rbuf, rlen, reply->key_mic); //printf("wpa_supplicant_process_2_of_4 exit\n"); printf("2/4x\n"); return 0; }
/** * wpa_supplicant_send_4_of_4 - Send message 4 of WPA/RSN 4-Way Handshake * @sm: Pointer to WPA state machine data from wpa_sm_init() * @dst: Destination address for the frame * @key: Pointer to the EAPOL-Key frame header * @ver: Version bits from EAPOL-Key Key Info * @key_info: Key Info * @kde: KDEs to include the EAPOL-Key frame * @kde_len: Length of KDEs * @ptk: PTK to use for keyed hash and encryption * Returns: 0 on success, -1 on failure */ int wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst, const struct wpa_eapol_key *key, u16 ver, u16 key_info, const u8 *kde, size_t kde_len, struct wpa_ptk *ptk) { size_t rlen; struct wpa_eapol_key *reply; u8 *rbuf; if (kde) wpa_hexdump(MSG_DEBUG, "WPA: KDE for msg 4/4", kde, kde_len); rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, sizeof(*reply) + kde_len, &rlen, (void *) &reply); if (rbuf == NULL) return -1; reply->type = sm->proto == WPA_PROTO_RSN ? EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; key_info &= WPA_KEY_INFO_SECURE; key_info |= ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_MIC; WPA_PUT_BE16(reply->key_info, key_info); if (sm->proto == WPA_PROTO_RSN) WPA_PUT_BE16(reply->key_length, 0); else os_memcpy(reply->key_length, key->key_length, 2); os_memcpy(reply->replay_counter, key->replay_counter, WPA_REPLAY_COUNTER_LEN); WPA_PUT_BE16(reply->key_data_length, kde_len); if (kde) os_memcpy(reply + 1, kde, kde_len); wpa_printf(MSG_DEBUG, "WPA: Sending EAPOL-Key 4/4"); wpa_eapol_key_send(sm, ptk->kck, ver, dst, ETH_P_EAPOL, rbuf, rlen, reply->key_mic); return 0; }
/** * wpa_sm_stkstart - Send EAPOL-Key Request for STK handshake (STK M1) * @sm: Pointer to WPA state machine data from wpa_sm_init() * @peer: MAC address of the peer STA * Returns: 0 on success, or -1 on failure * * Send an EAPOL-Key Request to the current authenticator to start STK * handshake with the peer. */ int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer) { size_t rlen, kde_len; struct wpa_eapol_key *req; int key_info, ver; u8 bssid[ETH_ALEN], *rbuf, *pos, *count_pos; u16 count; struct rsn_ie_hdr *hdr; struct wpa_peerkey *peerkey; struct wpa_ie_data ie; if (sm->proto != WPA_PROTO_RSN || !sm->ptk_set || !sm->peerkey_enabled) return -1; if (sm->ap_rsn_ie && wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &ie) == 0 && !(ie.capabilities & WPA_CAPABILITY_PEERKEY_ENABLED)) { wpa_printf(MSG_DEBUG, "RSN: Current AP does not support STK"); return -1; } if (sm->pairwise_cipher == WPA_CIPHER_CCMP) ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; else ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; if (wpa_sm_get_bssid(sm, bssid) < 0) { wpa_printf(MSG_WARNING, "Failed to read BSSID for EAPOL-Key " "SMK M1"); return -1; } /* TODO: find existing entry and if found, use that instead of adding * a new one */ peerkey = os_zalloc(sizeof(*peerkey)); if (peerkey == NULL) return -1; peerkey->initiator = 1; os_memcpy(peerkey->addr, peer, ETH_ALEN); #ifdef CONFIG_IEEE80211W if (wpa_key_mgmt_sha256(sm->key_mgmt)) peerkey->use_sha256 = 1; #endif /* CONFIG_IEEE80211W */ /* SMK M1: * EAPOL-Key(S=1, M=1, A=0, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce, * MIC=MIC, DataKDs=(RSNIE_I, MAC_P KDE)) */ hdr = (struct rsn_ie_hdr *) peerkey->rsnie_i; hdr->elem_id = WLAN_EID_RSN; WPA_PUT_LE16(hdr->version, RSN_VERSION); pos = (u8 *) (hdr + 1); /* Group Suite can be anything for SMK RSN IE; receiver will just * ignore it. */ RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); pos += RSN_SELECTOR_LEN; count_pos = pos; pos += 2; count = 0; if (sm->allowed_pairwise_cipher & WPA_CIPHER_CCMP) { RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); pos += RSN_SELECTOR_LEN; count++; } if (sm->allowed_pairwise_cipher & WPA_CIPHER_TKIP) { RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); pos += RSN_SELECTOR_LEN; count++; } WPA_PUT_LE16(count_pos, count); hdr->len = (pos - peerkey->rsnie_i) - 2; peerkey->rsnie_i_len = pos - peerkey->rsnie_i; wpa_hexdump(MSG_DEBUG, "WPA: RSN IE for SMK handshake", peerkey->rsnie_i, peerkey->rsnie_i_len); kde_len = peerkey->rsnie_i_len + 2 + RSN_SELECTOR_LEN + ETH_ALEN; rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, sizeof(*req) + kde_len, &rlen, (void *) &req); if (rbuf == NULL) { wpa_supplicant_peerkey_free(sm, peerkey); return -1; } req->type = EAPOL_KEY_TYPE_RSN; key_info = WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC | WPA_KEY_INFO_SECURE | WPA_KEY_INFO_REQUEST | ver; WPA_PUT_BE16(req->key_info, key_info); WPA_PUT_BE16(req->key_length, 0); os_memcpy(req->replay_counter, sm->request_counter, WPA_REPLAY_COUNTER_LEN); inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN); if (random_get_bytes(peerkey->inonce, WPA_NONCE_LEN)) { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: Failed to get random data for INonce"); os_free(rbuf); wpa_supplicant_peerkey_free(sm, peerkey); return -1; } os_memcpy(req->key_nonce, peerkey->inonce, WPA_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "WPA: INonce for SMK handshake", req->key_nonce, WPA_NONCE_LEN); WPA_PUT_BE16(req->key_data_length, (u16) kde_len); pos = (u8 *) (req + 1); /* Initiator RSN IE */ pos = wpa_add_ie(pos, peerkey->rsnie_i, peerkey->rsnie_i_len); /* Peer MAC address KDE */ wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN); wpa_printf(MSG_INFO, "RSN: Sending EAPOL-Key SMK M1 Request (peer " MACSTR ")", MAC2STR(peer)); wpa_eapol_key_send(sm, sm->ptk.kck, ver, bssid, ETH_P_EAPOL, rbuf, rlen, req->key_mic); peerkey->next = sm->peerkey; sm->peerkey = peerkey; return 0; }
/** * wpa_supplicant_send_2_of_4 - Send message 2 of WPA/RSN 4-Way Handshake * @sm: Pointer to WPA state machine data from wpa_sm_init() * @dst: Destination address for the frame * @key: Pointer to the EAPOL-Key frame header * @ver: Version bits from EAPOL-Key Key Info * @nonce: Nonce value for the EAPOL-Key frame * @wpa_ie: WPA/RSN IE * @wpa_ie_len: Length of the WPA/RSN IE * @ptk: PTK to use for keyed hash and encryption * Returns: 0 on success, -1 on failure */ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst, const struct wpa_eapol_key *key, int ver, const u8 *nonce, const u8 *wpa_ie, size_t wpa_ie_len, struct wpa_ptk *ptk) { size_t rlen; struct wpa_eapol_key *reply; u8 *rbuf; u8 *rsn_ie_buf = NULL; if (wpa_ie == NULL) { wpa_printf(MSG_WARNING, "WPA: No wpa_ie set - cannot " "generate msg 2/4"); return -1; } #ifdef CONFIG_IEEE80211R if (wpa_key_mgmt_ft(sm->key_mgmt)) { int res; /* * Add PMKR1Name into RSN IE (PMKID-List) and add MDIE and * FTIE from (Re)Association Response. */ rsn_ie_buf = os_malloc(wpa_ie_len + 2 + 2 + PMKID_LEN + sm->assoc_resp_ies_len); if (rsn_ie_buf == NULL) return -1; os_memcpy(rsn_ie_buf, wpa_ie, wpa_ie_len); res = wpa_insert_pmkid(rsn_ie_buf, wpa_ie_len, sm->pmk_r1_name); if (res < 0) { os_free(rsn_ie_buf); return -1; } wpa_ie_len += res; if (sm->assoc_resp_ies) { os_memcpy(rsn_ie_buf + wpa_ie_len, sm->assoc_resp_ies, sm->assoc_resp_ies_len); wpa_ie_len += sm->assoc_resp_ies_len; } wpa_ie = rsn_ie_buf; } #endif /* CONFIG_IEEE80211R */ wpa_hexdump(MSG_DEBUG, "WPA: WPA IE for msg 2/4", wpa_ie, wpa_ie_len); rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, sizeof(*reply) + wpa_ie_len, &rlen, (void *) &reply); if (rbuf == NULL) { os_free(rsn_ie_buf); return -1; } reply->type = sm->proto == WPA_PROTO_RSN ? EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; WPA_PUT_BE16(reply->key_info, ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_MIC); if (sm->proto == WPA_PROTO_RSN) WPA_PUT_BE16(reply->key_length, 0); else os_memcpy(reply->key_length, key->key_length, 2); os_memcpy(reply->replay_counter, key->replay_counter, WPA_REPLAY_COUNTER_LEN); WPA_PUT_BE16(reply->key_data_length, wpa_ie_len); os_memcpy(reply + 1, wpa_ie, wpa_ie_len); os_free(rsn_ie_buf); os_memcpy(reply->key_nonce, nonce, WPA_NONCE_LEN); wpa_printf(MSG_DEBUG, "WPA: Sending EAPOL-Key 2/4"); wpa_eapol_key_send(sm, ptk->kck, ver, dst, ETH_P_EAPOL, rbuf, rlen, reply->key_mic); return 0; }