}
+static void wpa_supplicant_key_mgmt_set_pmk(struct wpa_sm *sm)
+{
+#ifdef CONFIG_IEEE80211R
+ if (sm->key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X) {
+ if (wpa_sm_key_mgmt_set_pmk(sm, sm->xxkey, sm->xxkey_len))
+ wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
+ "RSN: Cannot set low order 256 bits of MSK for key management offload");
+ } else {
+#endif /* CONFIG_IEEE80211R */
+ if (wpa_sm_key_mgmt_set_pmk(sm, sm->pmk, sm->pmk_len))
+ wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
+ "RSN: Cannot set PMK for key management offload");
+#ifdef CONFIG_IEEE80211R
+ }
+#endif /* CONFIG_IEEE80211R */
+}
+
+
static int wpa_supplicant_get_pmk(struct wpa_sm *sm,
const unsigned char *src_addr,
const u8 *pmkid)
}
if (pmkid && sm->cur_pmksa &&
- os_memcmp(pmkid, sm->cur_pmksa->pmkid, PMKID_LEN) == 0) {
+ os_memcmp_const(pmkid, sm->cur_pmksa->pmkid, PMKID_LEN) == 0) {
wpa_hexdump(MSG_DEBUG, "RSN: matched PMKID", pmkid, PMKID_LEN);
wpa_sm_set_pmk_from_pmksa(sm);
wpa_hexdump_key(MSG_DEBUG, "RSN: PMK from PMKSA cache",
wpa_hexdump_key(MSG_DEBUG, "WPA: PMK from EAPOL state "
"machines", sm->pmk, pmk_len);
sm->pmk_len = pmk_len;
+ wpa_supplicant_key_mgmt_set_pmk(sm);
if (sm->proto == WPA_PROTO_RSN &&
+ !wpa_key_mgmt_suite_b(sm->key_mgmt) &&
!wpa_key_mgmt_ft(sm->key_mgmt)) {
sa = pmksa_cache_add(sm->pmksa,
sm->pmk, pmk_len,
+ NULL, 0,
src_addr, sm->own_addr,
sm->network_ctx,
sm->key_mgmt);
}
if (abort_cached && wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt) &&
+ !wpa_key_mgmt_suite_b(sm->key_mgmt) &&
!wpa_key_mgmt_ft(sm->key_mgmt) && sm->key_mgmt != WPA_KEY_MGMT_OSEN)
{
/* Send EAPOL-Start to trigger full EAP authentication. */
return -1;
}
- if (os_memcmp(rsn.pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN) != 0) {
+ if (os_memcmp_const(rsn.pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN) != 0)
+ {
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
"FT: PMKR1Name mismatch in "
"FT 4-way handshake message 3/4");
if (ie.gtk)
wpa_sm_set_rekey_offload(sm);
+ if (sm->proto == WPA_PROTO_RSN && wpa_key_mgmt_suite_b(sm->key_mgmt)) {
+ struct rsn_pmksa_cache_entry *sa;
+
+ sa = pmksa_cache_add(sm->pmksa, sm->pmk, sm->pmk_len,
+ sm->ptk.kck, sizeof(sm->ptk.kck),
+ sm->bssid, sm->own_addr,
+ sm->network_ctx, sm->key_mgmt);
+ if (!sm->cur_pmksa)
+ sm->cur_pmksa = sa;
+ }
+
return;
failed:
(unsigned long) maxkeylen);
return -1;
}
- if (aes_unwrap(sm->ptk.kek, maxkeylen / 8, key_data, gd->gtk)) {
+ if (aes_unwrap(sm->ptk.kek, 16, maxkeylen / 8, key_data,
+ gd->gtk)) {
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
"WPA: AES unwrap failed - could not decrypt "
"GTK");
os_memset(key->key_mic, 0, 16);
wpa_eapol_key_mic(sm->tptk.kck, ver, buf, len,
key->key_mic);
- if (os_memcmp(mic, key->key_mic, 16) != 0) {
+ if (os_memcmp_const(mic, key->key_mic, 16) != 0) {
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
"WPA: Invalid EAPOL-Key MIC "
"when using TPTK - ignoring TPTK");
os_memset(key->key_mic, 0, 16);
wpa_eapol_key_mic(sm->ptk.kck, ver, buf, len,
key->key_mic);
- if (os_memcmp(mic, key->key_mic, 16) != 0) {
+ if (os_memcmp_const(mic, key->key_mic, 16) != 0) {
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
"WPA: Invalid EAPOL-Key MIC - "
"dropping packet");
"WPA: No memory for AES-UNWRAP buffer");
return -1;
}
- if (aes_unwrap(sm->ptk.kek, *key_data_len / 8,
+ if (aes_unwrap(sm->ptk.kek, 16, *key_data_len / 8,
key_data, buf)) {
os_free(buf);
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
"WPA: Backwards compatibility: allow invalid "
"version for non-CCMP group keys");
+ } else if (ver == WPA_KEY_INFO_TYPE_AES_128_CMAC) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "WPA: Interoperability workaround: allow incorrect (should have been HMAC-SHA1), but stronger (is AES-128-CMAC), descriptor version to be used");
} else
goto out;
} else if (sm->pairwise_cipher == WPA_CIPHER_GCMP &&
WPA_AUTH_KEY_MGMT_CCKM);
case WPA_KEY_MGMT_WPA_NONE:
return WPA_AUTH_KEY_MGMT_NONE;
+ case WPA_KEY_MGMT_IEEE8021X_SUITE_B:
+ return RSN_AUTH_KEY_MGMT_802_1X_SUITE_B;
default:
return 0;
}
* @sm: Pointer to WPA state machine data from wpa_sm_init()
* @pmk: The new PMK
* @pmk_len: The length of the new PMK in bytes
+ * @bssid: AA to add into PMKSA cache or %NULL to not cache the PMK
*
* Configure the PMK for WPA state machine.
*/
-void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len)
+void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len,
+ const u8 *bssid)
{
if (sm == NULL)
return;
sm->xxkey_len = pmk_len;
os_memcpy(sm->xxkey, pmk, pmk_len);
#endif /* CONFIG_IEEE80211R */
+
+ if (bssid) {
+ pmksa_cache_add(sm->pmksa, pmk, pmk_len, NULL, 0,
+ bssid, sm->own_addr,
+ sm->network_ctx, sm->key_mgmt);
+ }
}
}
#endif /* CONFIG_P2P */
+
+
+void wpa_sm_set_rx_replay_ctr(struct wpa_sm *sm, const u8 *rx_replay_counter)
+{
+ if (rx_replay_counter == NULL)
+ return;
+
+ os_memcpy(sm->rx_replay_counter, rx_replay_counter,
+ WPA_REPLAY_COUNTER_LEN);
+ sm->rx_replay_counter_set = 1;
+ wpa_printf(MSG_DEBUG, "Updated key replay counter");
+}
+
+
+void wpa_sm_set_ptk_kck_kek(struct wpa_sm *sm, const u8 *ptk_kck,
+ const u8 *ptk_kek)
+{
+ if (ptk_kck) {
+ os_memcpy(sm->ptk.kck, ptk_kck, 16);
+ wpa_printf(MSG_DEBUG, "Updated PTK KCK");
+ }
+ if (ptk_kek) {
+ os_memcpy(sm->ptk.kek, ptk_kek, 16);
+ wpa_printf(MSG_DEBUG, "Updated PTK KEK");
+ }
+ sm->ptk_set = 1;
+}