static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, const struct wpa_eapol_key *key, u16 ver) { u16 key_info, keylen, len; const u8 *pos; struct wpa_eapol_ie_parse ie; wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE); wpa_printf(MSG_DEBUG, "WPA: RX message 3 of 4-Way Handshake from " MACSTR " (ver=%d)", MAC2STR(sm->bssid), ver); key_info = WPA_GET_BE16(key->key_info); pos = (const u8 *) (key + 1); len = WPA_GET_BE16(key->key_data_length); wpa_hexdump(MSG_DEBUG, "WPA: IE KeyData", pos, len); wpa_supplicant_parse_ies(pos, len, &ie); if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { wpa_printf(MSG_WARNING, "WPA: GTK IE in unencrypted key data"); goto failed; } #ifdef CONFIG_IEEE80211W if (ie.igtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { wpa_printf(MSG_WARNING, "WPA: IGTK KDE in unencrypted key " "data"); goto failed; } if (ie.igtk && ie.igtk_len != sizeof(struct wpa_igtk_kde)) { wpa_printf(MSG_WARNING, "WPA: Invalid IGTK KDE length %lu", (unsigned long) ie.igtk_len); goto failed; } #endif /* CONFIG_IEEE80211W */ if (wpa_supplicant_validate_ie(sm, sm->bssid, &ie) < 0) goto failed; if (os_memcmp(sm->anonce, key->key_nonce, WPA_NONCE_LEN) != 0) { wpa_printf(MSG_WARNING, "WPA: ANonce from message 1 of 4-Way " "Handshake differs from 3 of 4-Way Handshake - drop" " packet (src=" MACSTR ")", MAC2STR(sm->bssid)); goto failed; } keylen = WPA_GET_BE16(key->key_length); switch (sm->pairwise_cipher) { case WPA_CIPHER_CCMP: if (keylen != 16) { wpa_printf(MSG_WARNING, "WPA: Invalid CCMP key length " "%d (src=" MACSTR ")", keylen, MAC2STR(sm->bssid)); goto failed; } break; case WPA_CIPHER_TKIP: if (keylen != 32) { wpa_printf(MSG_WARNING, "WPA: Invalid TKIP key length " "%d (src=" MACSTR ")", keylen, MAC2STR(sm->bssid)); goto failed; } break; } if (wpa_supplicant_send_4_of_4(sm, sm->bssid, key, ver, key_info, NULL, 0, &sm->ptk)) { goto failed; } /* SNonce was successfully used in msg 3/4, so mark it to be renewed * for the next 4-Way Handshake. If msg 3 is received again, the old * SNonce will still be used to avoid changing PTK. */ sm->renew_snonce = 1; if (key_info & WPA_KEY_INFO_INSTALL) { if (wpa_supplicant_install_ptk(sm, key)) goto failed; } if (key_info & WPA_KEY_INFO_SECURE) { wpa_sm_mlme_setprotection( sm, sm->bssid, MLME_SETPROTECTION_PROTECT_TYPE_RX, MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); eapol_sm_notify_portValid(sm->eapol, TRUE); } wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE); if (ie.gtk && wpa_supplicant_pairwise_gtk(sm, key, ie.gtk, ie.gtk_len, key_info) < 0) { wpa_printf(MSG_INFO, "RSN: Failed to configure GTK"); goto failed; } if (ieee80211w_set_keys(sm, &ie) < 0) { wpa_printf(MSG_INFO, "RSN: Failed to configure IGTK"); goto failed; } return; failed: wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED); }
static void wpa_supplicant_process_stk_3_of_4(struct wpa_sm *sm, struct wpa_peerkey *peerkey, const struct wpa_eapol_key *key, u16 ver) { struct wpa_eapol_ie_parse kde; const u8 *keydata; size_t len, key_len; const u8 *_key; u8 key_buf[32], rsc[6]; wpa_printf(MSG_DEBUG, "RSN: RX message 3 of STK 4-Way Handshake from " MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver); os_memset(&kde, 0, sizeof(kde)); /* RSN: msg 3/4 should contain Initiator RSN IE. It may also include * Lifetime KDE. */ keydata = (const u8 *) (key + 1); len = WPA_GET_BE16(key->key_data_length); wpa_hexdump(MSG_DEBUG, "RSN: msg 3/4 key data", keydata, len); if (wpa_supplicant_parse_ies(keydata, len, &kde) < 0) { wpa_printf(MSG_DEBUG, "RSN: Failed to parse key data in " "STK 3/4"); return; } if (kde.rsn_ie_len != peerkey->rsnie_i_len || os_memcmp(kde.rsn_ie, peerkey->rsnie_i, kde.rsn_ie_len) != 0) { wpa_printf(MSG_INFO, "RSN: Initiator RSN IE in SMK and STK " "handshakes did not match"); wpa_hexdump(MSG_DEBUG, "RSN: Initiator RSN IE in SMK " "handshake", peerkey->rsnie_i, peerkey->rsnie_i_len); wpa_hexdump(MSG_DEBUG, "RSN: Initiator RSN IE in STK " "handshake", kde.rsn_ie, kde.rsn_ie_len); return; } if (os_memcmp(peerkey->inonce, key->key_nonce, WPA_NONCE_LEN) != 0) { wpa_printf(MSG_WARNING, "RSN: INonce from message 1 of STK " "4-Way Handshake differs from 3 of STK 4-Way " "Handshake - drop packet (src=" MACSTR ")", MAC2STR(peerkey->addr)); return; } wpa_supplicant_update_smk_lifetime(sm, peerkey, &kde); if (wpa_supplicant_send_4_of_4(sm, peerkey->addr, key, ver, WPA_GET_BE16(key->key_info), NULL, 0, &peerkey->stk)) return; _key = (u8 *) peerkey->stk.tk1; if (peerkey->cipher == WPA_CIPHER_TKIP) { /* Swap Tx/Rx keys for Michael MIC */ os_memcpy(key_buf, _key, 16); os_memcpy(key_buf + 16, peerkey->stk.u.auth.rx_mic_key, 8); os_memcpy(key_buf + 24, peerkey->stk.u.auth.tx_mic_key, 8); _key = key_buf; key_len = 32; } else key_len = 16; os_memset(rsc, 0, 6); if (wpa_sm_set_key(sm, peerkey->cipher, peerkey->addr, 0, 1, rsc, sizeof(rsc), _key, key_len) < 0) { wpa_printf(MSG_WARNING, "RSN: Failed to set STK to the " "driver."); return; } }
static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, const struct wpa_eapol_key *key, //size 95 u16 ver) { u16 key_info, keylen, len; const u8 *pos; struct wpa_eapol_ie_parse ie; lwip_log("WPA: RX message 3 of 4-Way Handshake from " MACSTR " (ver=%d)\n", MAC2STR(sm->bssid), ver); key_info = WPA_GET_BE16(key->key_info); pos = (const u8 *) (key + 1); len = WPA_GET_BE16(key->key_data_length); wpa_hexdump(MSG_DEBUG, "WPA: IE KeyData", pos, len); wpa_supplicant_parse_ies(pos, len, &ie); if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { lwip_log("WPA: GTK IE in unencrypted key data\n"); return; } /* if (wpa_supplicant_validate_ie(sm, sm->bssid, &ie) < 0) { return; } */ if (os_memcmp(sm->anonce, key->key_nonce, WPA_NONCE_LEN) != 0) { lwip_log("WPA: ANonce from message 1 of 4-Way Handshake differs from 3 of 4-Way Handshake - drop" " packet (src=" MACSTR ")\n", MAC2STR(sm->bssid)); return; } keylen = WPA_GET_BE16(key->key_length); switch (sm->pairwise_cipher) { case WPA_CIPHER_CCMP: if (keylen != 16) { lwip_log("WPA: Invalid CCMP key length %d (src=" MACSTR ")\n", keylen, MAC2STR(sm->bssid)); return; } break; case WPA_CIPHER_TKIP: if (keylen != 32) { lwip_log("WPA: Invalid TKIP key length %d (src=" MACSTR ")\n", keylen, MAC2STR(sm->bssid)); return; } break; } if (wpa_supplicant_send_4_of_4(sm, sm->bssid, key, ver, key_info, NULL, 0, &sm->ptk)) { return; } /* SNonce was successfully used in msg 3/4, so mark it to be renewed * for the next 4-Way Handshake. If msg 3 is received again, the old * SNonce will still be used to avoid changing PTK. */ sm->renew_snonce = 1; if (key_info & WPA_KEY_INFO_INSTALL) { wpa_supplicant_install_ptk(sm, key); } if (key_info & WPA_KEY_INFO_SECURE) { // wpa_sm_mlme_setprotection( // sm, sm->bssid, MLME_SETPROTECTION_PROTECT_TYPE_RX, // MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); // eapol_sm_notify_portValid(sm->eapol, TRUE); } // wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE); if (ie.gtk && wpa_supplicant_pairwise_gtk(sm, key, ie.gtk, ie.gtk_len, key_info) < 0) { lwip_log("RSN: Failed to configure GTK\n"); } #if 1 MSG_SET_WPA_SH(); #else if (ieee80211w_set_keys(sm, &ie) < 0) { lwip_log("RSN: Failed to configure DHV/IGTK\n"); } else { MSG_SET_WPA_SH(); } #endif }