if (sm == NULL)
return;
- if (sm->wpa_auth->conf.wpa_deny_ptk0_rekey) {
+ if (!sm->use_ext_key_id && sm->wpa_auth->conf.wpa_deny_ptk0_rekey) {
wpa_printf(MSG_INFO,
"WPA: PTK0 rekey not allowed, disconnect " MACSTR,
MAC2STR(sm->addr));
sm->disconnect_reason =
WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA;
} else {
+ if (sm->use_ext_key_id)
+ sm->keyidx_active ^= 1; /* flip Key ID */
sm->PTKRequest = TRUE;
sm->PTK_valid = 0;
}
0, KEY_FLAG_PAIRWISE))
wpa_printf(MSG_DEBUG,
"RSN: PTK removal from the driver failed");
+ if (sm->wpa_auth->conf.extended_key_id && sm->use_ext_key_id &&
+ wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 1, NULL,
+ 0, KEY_FLAG_PAIRWISE))
+ wpa_printf(MSG_DEBUG,
+ "RSN: PTK Key ID 1 removal from the driver failed");
sm->pairwise_set = FALSE;
eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm);
}
sm->Init = FALSE;
sm->AuthenticationRequest = TRUE;
break;
- } else if (sm->wpa_auth->conf.wpa_deny_ptk0_rekey) {
+ }
+
+ if (!sm->use_ext_key_id &&
+ sm->wpa_auth->conf.wpa_deny_ptk0_rekey) {
wpa_printf(MSG_INFO,
"WPA: PTK0 rekey not allowed, disconnect "
MACSTR, MAC2STR(sm->addr));
sm->Disconnect = TRUE;
- /* Try to encourage the STA reconnect */
+ /* Try to encourage the STA to reconnect */
sm->disconnect_reason =
WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA;
break;
}
+
+ if (sm->use_ext_key_id)
+ sm->keyidx_active ^= 1; /* flip Key ID */
+
if (sm->GUpdateStationKeys) {
/*
* Reauthentication cancels the pending group key
u8 *wpa_ie;
int secure, gtkidx, encr = 0;
u8 *wpa_ie_buf = NULL, *wpa_ie_buf2 = NULL;
+ u8 hdr[2];
SM_ENTRY_MA(WPA_PTK, PTKINITNEGOTIATING, wpa_ptk);
sm->TimeoutEvt = FALSE;
wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
"sending 3/4 msg of 4-Way Handshake");
if (sm->wpa == WPA_VERSION_WPA2) {
+ if (sm->use_ext_key_id && sm->TimeoutCtr == 1 &&
+ wpa_auth_set_key(sm->wpa_auth, 0,
+ wpa_cipher_to_alg(sm->pairwise),
+ sm->addr,
+ sm->keyidx_active, sm->PTK.tk,
+ wpa_cipher_key_len(sm->pairwise),
+ KEY_FLAG_PAIRWISE_RX)) {
+ wpa_sta_disconnect(sm->wpa_auth, sm->addr,
+ WLAN_REASON_PREV_AUTH_NOT_VALID);
+ return;
+ }
+
/* WPA2 send GTK in the 4-way handshake */
secure = 1;
gtk = gsm->GTK[gsm->GN - 1];
}
kde_len = wpa_ie_len + ieee80211w_kde_len(sm) + ocv_oci_len(sm);
+
+ if (sm->use_ext_key_id)
+ kde_len += 2 + RSN_SELECTOR_LEN + 2;
+
if (gtk)
kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len;
#ifdef CONFIG_IEEE80211R_AP
pos += elen;
}
#endif /* CONFIG_IEEE80211R_AP */
+ hdr[1] = 0;
+
+ if (sm->use_ext_key_id) {
+ hdr[0] = sm->keyidx_active & 0x01;
+ pos = wpa_add_kde(pos, RSN_KEY_DATA_KEYID, hdr, 2, NULL, 0);
+ }
+
if (gtk) {
- u8 hdr[2];
hdr[0] = gtkidx & 0x03;
- hdr[1] = 0;
pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
gtk, gtk_len);
}
if (sm->Pair) {
enum wpa_alg alg = wpa_cipher_to_alg(sm->pairwise);
int klen = wpa_cipher_key_len(sm->pairwise);
- if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0,
- sm->PTK.tk, klen,
- KEY_FLAG_PAIRWISE_RX_TX)) {
+ int res;
+
+ if (sm->use_ext_key_id)
+ res = wpa_auth_set_key(sm->wpa_auth, 0, 0, sm->addr,
+ sm->keyidx_active, NULL, 0,
+ KEY_FLAG_PAIRWISE_RX_TX_MODIFY);
+ else
+ res = wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr,
+ 0, sm->PTK.tk, klen,
+ KEY_FLAG_PAIRWISE_RX_TX);
+ if (res) {
wpa_sta_disconnect(sm->wpa_auth, sm->addr,
WLAN_REASON_PREV_AUTH_NOT_VALID);
return;
struct wpa_group *gsm = sm->group;
u8 *wpa_ie;
int wpa_ie_len, secure, gtkidx, encr = 0;
+ u8 hdr[2];
/* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE],
GTK[GN], IGTK, [BIGTK], [FTIE], [TIE * 2])
}
kde_len = wpa_ie_len + ieee80211w_kde_len(sm) + ocv_oci_len(sm);
+
+ if (sm->use_ext_key_id)
+ kde_len += 2 + RSN_SELECTOR_LEN + 2;
+
if (gtk)
kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len;
#ifdef CONFIG_IEEE80211R_AP
pos += elen;
}
#endif /* CONFIG_IEEE80211R_AP */
+ hdr[1] = 0;
+
+ if (sm->use_ext_key_id) {
+ hdr[0] = sm->keyidx_active & 0x01;
+ pos = wpa_add_kde(pos, RSN_KEY_DATA_KEYID, hdr, 2, NULL, 0);
+ }
+
if (gtk) {
- u8 hdr[2];
hdr[0] = gtkidx & 0x03;
- hdr[1] = 0;
pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
gtk, gtk_len);
}
os_memset(wconf, 0, sizeof(*wconf));
wconf->wpa = conf->wpa;
+ wconf->extended_key_id = conf->extended_key_id;
wconf->wpa_key_mgmt = conf->wpa_key_mgmt;
wconf->wpa_pairwise = conf->wpa_pairwise;
wconf->wpa_group = conf->wpa_group;
}
#ifdef CONFIG_TESTING_OPTIONS
- if (addr && !is_broadcast_ether_addr(addr)) {
+ if (key_flag & KEY_FLAG_MODIFY) {
+ /* We are updating an already installed key. Don't overwrite
+ * the already stored key information with zeros.
+ */
+ } else if (addr && !is_broadcast_ether_addr(addr)) {
struct sta_info *sta;
sta = ap_get_sta(hapd, addr);
_conf.wpa_deny_ptk0_rekey = 1;
}
+ if (_conf.extended_key_id &&
+ (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID))
+ wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Extended Key ID supported");
+ else
+ _conf.extended_key_id = 0;
+
hapd->wpa_auth = wpa_init(hapd->own_addr, &_conf, &cb, hapd);
if (hapd->wpa_auth == NULL) {
wpa_printf(MSG_ERROR, "WPA initialization failed.");
if (rsn_testing)
capab |= BIT(8) | BIT(15);
#endif /* CONFIG_RSN_TESTING */
+ if (conf->extended_key_id)
+ capab |= WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST;
WPA_PUT_LE16(pos, capab);
pos += 2;
const u8 *mdie, size_t mdie_len,
const u8 *owe_dh, size_t owe_dh_len)
{
+ struct wpa_auth_config *conf = &wpa_auth->conf;
struct wpa_ie_data data;
int ciphers, key_mgmt, res, version;
u32 selector;
}
#endif /* CONFIG_DPP */
+ if (conf->extended_key_id && sm->wpa == WPA_VERSION_WPA2 &&
+ sm->pairwise != WPA_CIPHER_TKIP &&
+ (data.capabilities & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST)) {
+ sm->use_ext_key_id = TRUE;
+ if (conf->extended_key_id == 2 &&
+ !wpa_key_mgmt_ft(sm->wpa_key_mgmt) &&
+ !wpa_key_mgmt_fils(sm->wpa_key_mgmt))
+ sm->keyidx_active = 1;
+ else
+ sm->keyidx_active = 0;
+ wpa_printf(MSG_DEBUG,
+ "RSN: Extended Key ID supported (start with %d)",
+ sm->keyidx_active);
+ } else {
+ sm->use_ext_key_id = FALSE;
+ }
+
if (sm->wpa_ie == NULL || sm->wpa_ie_len < wpa_ie_len) {
os_free(sm->wpa_ie);
sm->wpa_ie = os_malloc(wpa_ie_len);