static int wpa_supplicant_process_1_of_2_rsn(struct wpa_sm *sm, const u8 *keydata, size_t keydatalen, u16 key_info, struct wpa_gtk_data *gd) { int maxkeylen; struct wpa_eapol_ie_parse ie; wpa_hexdump(MSG_DEBUG, "RSN: msg 1/2 key data", keydata, keydatalen); wpa_supplicant_parse_ies(keydata, keydatalen, &ie); if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { wpa_printf(MSG_WARNING, "WPA: GTK IE in unencrypted key data"); return -1; } if (ie.gtk == NULL) { wpa_printf(MSG_INFO, "WPA: No GTK IE in Group Key msg 1/2"); return -1; } maxkeylen = gd->gtk_len = ie.gtk_len - 2; if (wpa_supplicant_check_group_cipher(sm->group_cipher, gd->gtk_len, maxkeylen, &gd->key_rsc_len, &gd->alg)) return -1; wpa_hexdump(MSG_DEBUG, "RSN: received GTK in group key handshake", ie.gtk, ie.gtk_len); gd->keyidx = ie.gtk[0] & 0x3; gd->tx = wpa_supplicant_gtk_tx_bit_workaround(sm, !!(ie.gtk[0] & BIT(2))); if (ie.gtk_len - 2 > sizeof(gd->gtk)) { wpa_printf(MSG_INFO, "RSN: Too long GTK in GTK IE " "(len=%lu)", (unsigned long) ie.gtk_len - 2); return -1; } os_memcpy(gd->gtk, ie.gtk + 2, ie.gtk_len - 2); if (ieee80211w_set_keys(sm, &ie) < 0) wpa_printf(MSG_INFO, "RSN: Failed to configure IGTK"); return 0; }
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_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 }