diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index f1fa2cfa7..6b6fcf700 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -1310,6 +1310,14 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, /* Set static WEP keys again */ wpa_set_wep_keys(wpa_s, wpa_s->current_ssid); } + +#ifdef CONFIG_IBSS_RSN + if (wpa_s->current_ssid && + wpa_s->current_ssid->mode == WPAS_MODE_IBSS && + wpa_s->key_mgmt != WPA_KEY_MGMT_NONE && + wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) + ibss_rsn_connected(wpa_s->ibss_rsn); +#endif /* CONFIG_IBSS_RSN */ } diff --git a/wpa_supplicant/ibss_rsn.c b/wpa_supplicant/ibss_rsn.c index fa99c08bd..d4894a5b3 100644 --- a/wpa_supplicant/ibss_rsn.c +++ b/wpa_supplicant/ibss_rsn.c @@ -277,6 +277,15 @@ static int auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg, } } + if (ibss_rsn->init_in_progress && key_len <= + sizeof(ibss_rsn->init_gtk)) { + wpa_printf(MSG_DEBUG, "AUTH: Delay setting of initial TX GTK " + "until RSN IBSS is connected"); + ibss_rsn->init_gtk_idx = idx; + os_memcpy(ibss_rsn->init_gtk, key, key_len); + return 0; + } + return wpa_drv_set_key(ibss_rsn->wpa_s, alg, addr, idx, 1, seq, 6, key, key_len); } @@ -305,7 +314,9 @@ static int ibss_rsn_auth_init_group(struct ibss_rsn *ibss_rsn, cb.get_psk = auth_get_psk; cb.set_key = auth_set_key; + ibss_rsn->init_in_progress = 1; ibss_rsn->auth_group = wpa_init(own_addr, &conf, &cb); + ibss_rsn->init_in_progress = 0; if (ibss_rsn->auth_group == NULL) { wpa_printf(MSG_DEBUG, "AUTH: wpa_init() failed"); return -1; @@ -517,3 +528,22 @@ void ibss_rsn_set_psk(struct ibss_rsn *ibss_rsn, const u8 *psk) { os_memcpy(ibss_rsn->psk, psk, PMK_LEN); } + + +void ibss_rsn_connected(struct ibss_rsn *ibss_rsn) +{ + u8 seq[6]; + wpa_printf(MSG_DEBUG, "RSN: IBSS connected notification"); + if (ibss_rsn->init_gtk_idx) { + wpa_printf(MSG_DEBUG, "RSN: Set initial IBSS TX GTK"); + os_memset(seq, 0, sizeof(seq)); + if (wpa_drv_set_key(ibss_rsn->wpa_s, WPA_ALG_CCMP, + broadcast_ether_addr, + ibss_rsn->init_gtk_idx, + 1, seq, sizeof(seq), ibss_rsn->init_gtk, + 16) < 0) + wpa_printf(MSG_INFO, "RSN: Failed to set IBSS TX GTK"); + ibss_rsn->init_gtk_idx = 0; + os_memset(ibss_rsn->init_gtk, 0, sizeof(ibss_rsn->init_gtk)); + } +} diff --git a/wpa_supplicant/ibss_rsn.h b/wpa_supplicant/ibss_rsn.h index 11e63ad1b..4e81910df 100644 --- a/wpa_supplicant/ibss_rsn.h +++ b/wpa_supplicant/ibss_rsn.h @@ -36,6 +36,10 @@ struct ibss_rsn { struct wpa_authenticator *auth_group; struct ibss_rsn_peer *peers; u8 psk[PMK_LEN]; + + int init_in_progress; + int init_gtk_idx; + u8 init_gtk[16]; }; @@ -45,5 +49,6 @@ int ibss_rsn_start(struct ibss_rsn *ibss_rsn, const u8 *addr); int ibss_rsn_rx_eapol(struct ibss_rsn *ibss_rsn, const u8 *src_addr, const u8 *buf, size_t len); void ibss_rsn_set_psk(struct ibss_rsn *ibss_rsn, const u8 *psk); +void ibss_rsn_connected(struct ibss_rsn *ibss_rsn); #endif /* IBSS_RSN_H */