SAE: Fix PMKID calculation for PMKSA cache

The SAE PMKID is calculated with IEEE Std 802.11-2012 11.3.5.4, but the
PMKID was re-calculated with 11.6.1.3 and saved into PMKSA cache. Fix
this to save the PMKID calculated with 11.3.5.4 into the PMKSA cache.

Signed-off-by: Masashi Honma <masashi.honma@gmail.com>
This commit is contained in:
Masashi Honma 2016-02-15 11:23:37 +09:00 committed by Jouni Malinen
parent 1492fbb90c
commit 70c93963ed
13 changed files with 38 additions and 27 deletions

View file

@ -665,7 +665,7 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH); wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
sta->sae->state = SAE_ACCEPTED; sta->sae->state = SAE_ACCEPTED;
wpa_auth_pmksa_add_sae(hapd->wpa_auth, sta->addr, wpa_auth_pmksa_add_sae(hapd->wpa_auth, sta->addr,
sta->sae->pmk); sta->sae->pmk, sta->sae->pmkid);
} }
break; break;
case SAE_ACCEPTED: case SAE_ACCEPTED:

View file

@ -247,6 +247,7 @@ static void pmksa_cache_link_entry(struct rsn_pmksa_cache *pmksa,
* @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init() * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init()
* @pmk: The new pairwise master key * @pmk: The new pairwise master key
* @pmk_len: PMK length in bytes, usually PMK_LEN (32) * @pmk_len: PMK length in bytes, usually PMK_LEN (32)
* @pmkid: Calculated PMKID
* @kck: Key confirmation key or %NULL if not yet derived * @kck: Key confirmation key or %NULL if not yet derived
* @kck_len: KCK length in bytes * @kck_len: KCK length in bytes
* @aa: Authenticator address * @aa: Authenticator address
@ -263,7 +264,7 @@ static void pmksa_cache_link_entry(struct rsn_pmksa_cache *pmksa,
*/ */
struct rsn_pmksa_cache_entry * struct rsn_pmksa_cache_entry *
pmksa_cache_auth_add(struct rsn_pmksa_cache *pmksa, pmksa_cache_auth_add(struct rsn_pmksa_cache *pmksa,
const u8 *pmk, size_t pmk_len, const u8 *pmk, size_t pmk_len, const u8 *pmkid,
const u8 *kck, size_t kck_len, const u8 *kck, size_t kck_len,
const u8 *aa, const u8 *spa, int session_timeout, const u8 *aa, const u8 *spa, int session_timeout,
struct eapol_state_machine *eapol, int akmp) struct eapol_state_machine *eapol, int akmp)
@ -282,7 +283,9 @@ pmksa_cache_auth_add(struct rsn_pmksa_cache *pmksa,
return NULL; return NULL;
os_memcpy(entry->pmk, pmk, pmk_len); os_memcpy(entry->pmk, pmk, pmk_len);
entry->pmk_len = pmk_len; entry->pmk_len = pmk_len;
if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) if (pmkid)
os_memcpy(entry->pmkid, pmkid, PMKID_LEN);
else if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
rsn_pmkid_suite_b_192(kck, kck_len, aa, spa, entry->pmkid); rsn_pmkid_suite_b_192(kck, kck_len, aa, spa, entry->pmkid);
else if (wpa_key_mgmt_suite_b(akmp)) else if (wpa_key_mgmt_suite_b(akmp))
rsn_pmkid_suite_b(kck, kck_len, aa, spa, entry->pmkid); rsn_pmkid_suite_b(kck, kck_len, aa, spa, entry->pmkid);

View file

@ -48,7 +48,7 @@ struct rsn_pmksa_cache_entry * pmksa_cache_get_okc(
const u8 *pmkid); const u8 *pmkid);
struct rsn_pmksa_cache_entry * struct rsn_pmksa_cache_entry *
pmksa_cache_auth_add(struct rsn_pmksa_cache *pmksa, pmksa_cache_auth_add(struct rsn_pmksa_cache *pmksa,
const u8 *pmk, size_t pmk_len, const u8 *pmk, size_t pmk_len, const u8 *pmkid,
const u8 *kck, size_t kck_len, const u8 *kck, size_t kck_len,
const u8 *aa, const u8 *spa, int session_timeout, const u8 *aa, const u8 *spa, int session_timeout,
struct eapol_state_machine *eapol, int akmp); struct eapol_state_machine *eapol, int akmp);

View file

@ -3298,7 +3298,7 @@ int wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk,
pmk_len = PMK_LEN; pmk_len = PMK_LEN;
} }
if (pmksa_cache_auth_add(sm->wpa_auth->pmksa, pmk, pmk_len, if (pmksa_cache_auth_add(sm->wpa_auth->pmksa, pmk, pmk_len, NULL,
sm->PTK.kck, sm->PTK.kck_len, sm->PTK.kck, sm->PTK.kck_len,
sm->wpa_auth->addr, sm->addr, session_timeout, sm->wpa_auth->addr, sm->addr, session_timeout,
eapol, sm->wpa_key_mgmt)) eapol, sm->wpa_key_mgmt))
@ -3316,7 +3316,7 @@ int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth,
if (wpa_auth == NULL) if (wpa_auth == NULL)
return -1; return -1;
if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, len, if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, len, NULL,
NULL, 0, NULL, 0,
wpa_auth->addr, wpa_auth->addr,
sta_addr, session_timeout, eapol, sta_addr, session_timeout, eapol,
@ -3328,12 +3328,12 @@ int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth,
int wpa_auth_pmksa_add_sae(struct wpa_authenticator *wpa_auth, const u8 *addr, int wpa_auth_pmksa_add_sae(struct wpa_authenticator *wpa_auth, const u8 *addr,
const u8 *pmk) const u8 *pmk, const u8 *pmkid)
{ {
if (wpa_auth->conf.disable_pmksa_caching) if (wpa_auth->conf.disable_pmksa_caching)
return -1; return -1;
if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, PMK_LEN, if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, PMK_LEN, pmkid,
NULL, 0, NULL, 0,
wpa_auth->addr, addr, 0, NULL, wpa_auth->addr, addr, 0, NULL,
WPA_KEY_MGMT_SAE)) WPA_KEY_MGMT_SAE))

View file

@ -286,7 +286,7 @@ int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth,
int session_timeout, int session_timeout,
struct eapol_state_machine *eapol); struct eapol_state_machine *eapol);
int wpa_auth_pmksa_add_sae(struct wpa_authenticator *wpa_auth, const u8 *addr, int wpa_auth_pmksa_add_sae(struct wpa_authenticator *wpa_auth, const u8 *addr,
const u8 *pmk); const u8 *pmk, const u8 *pmkid);
void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth, void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth,
const u8 *sta_addr); const u8 *sta_addr);
int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id); int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id);

View file

@ -109,6 +109,7 @@ static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa)
* @pmksa: Pointer to PMKSA cache data from pmksa_cache_init() * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init()
* @pmk: The new pairwise master key * @pmk: The new pairwise master key
* @pmk_len: PMK length in bytes, usually PMK_LEN (32) * @pmk_len: PMK length in bytes, usually PMK_LEN (32)
* @pmkid: Calculated PMKID
* @kck: Key confirmation key or %NULL if not yet derived * @kck: Key confirmation key or %NULL if not yet derived
* @kck_len: KCK length in bytes * @kck_len: KCK length in bytes
* @aa: Authenticator address * @aa: Authenticator address
@ -124,7 +125,7 @@ static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa)
*/ */
struct rsn_pmksa_cache_entry * struct rsn_pmksa_cache_entry *
pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
const u8 *kck, size_t kck_len, const u8 *pmkid, const u8 *kck, size_t kck_len,
const u8 *aa, const u8 *spa, void *network_ctx, int akmp) const u8 *aa, const u8 *spa, void *network_ctx, int akmp)
{ {
struct rsn_pmksa_cache_entry *entry, *pos, *prev; struct rsn_pmksa_cache_entry *entry, *pos, *prev;
@ -141,7 +142,9 @@ pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
return NULL; return NULL;
os_memcpy(entry->pmk, pmk, pmk_len); os_memcpy(entry->pmk, pmk, pmk_len);
entry->pmk_len = pmk_len; entry->pmk_len = pmk_len;
if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) if (pmkid)
os_memcpy(entry->pmkid, pmkid, PMKID_LEN);
else if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
rsn_pmkid_suite_b_192(kck, kck_len, aa, spa, entry->pmkid); rsn_pmkid_suite_b_192(kck, kck_len, aa, spa, entry->pmkid);
else if (wpa_key_mgmt_suite_b(akmp)) else if (wpa_key_mgmt_suite_b(akmp))
rsn_pmkid_suite_b(kck, kck_len, aa, spa, entry->pmkid); rsn_pmkid_suite_b(kck, kck_len, aa, spa, entry->pmkid);
@ -344,7 +347,7 @@ pmksa_cache_clone_entry(struct rsn_pmksa_cache *pmksa,
struct rsn_pmksa_cache_entry *new_entry; struct rsn_pmksa_cache_entry *new_entry;
new_entry = pmksa_cache_add(pmksa, old_entry->pmk, old_entry->pmk_len, new_entry = pmksa_cache_add(pmksa, old_entry->pmk, old_entry->pmk_len,
NULL, 0, NULL, NULL, 0,
aa, pmksa->sm->own_addr, aa, pmksa->sm->own_addr,
old_entry->network_ctx, old_entry->akmp); old_entry->network_ctx, old_entry->akmp);
if (new_entry == NULL) if (new_entry == NULL)

View file

@ -57,7 +57,7 @@ struct rsn_pmksa_cache_entry * pmksa_cache_get(struct rsn_pmksa_cache *pmksa,
int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len); int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len);
struct rsn_pmksa_cache_entry * struct rsn_pmksa_cache_entry *
pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
const u8 *kck, size_t kck_len, const u8 *pmkid, const u8 *kck, size_t kck_len,
const u8 *aa, const u8 *spa, void *network_ctx, int akmp); const u8 *aa, const u8 *spa, void *network_ctx, int akmp);
struct rsn_pmksa_cache_entry * pmksa_cache_get_current(struct wpa_sm *sm); struct rsn_pmksa_cache_entry * pmksa_cache_get_current(struct wpa_sm *sm);
void pmksa_cache_clear_current(struct wpa_sm *sm); void pmksa_cache_clear_current(struct wpa_sm *sm);
@ -105,7 +105,7 @@ static inline int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf,
static inline struct rsn_pmksa_cache_entry * static inline struct rsn_pmksa_cache_entry *
pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
const u8 *kck, size_t kck_len, const u8 *pmkid, const u8 *kck, size_t kck_len,
const u8 *aa, const u8 *spa, void *network_ctx, int akmp) const u8 *aa, const u8 *spa, void *network_ctx, int akmp)
{ {
return NULL; return NULL;

View file

@ -93,7 +93,7 @@ static void rsn_preauth_eapol_cb(struct eapol_sm *eapol,
wpa_hexdump_key(MSG_DEBUG, "RSN: PMK from pre-auth", wpa_hexdump_key(MSG_DEBUG, "RSN: PMK from pre-auth",
pmk, pmk_len); pmk, pmk_len);
sm->pmk_len = pmk_len; sm->pmk_len = pmk_len;
pmksa_cache_add(sm->pmksa, pmk, pmk_len, pmksa_cache_add(sm->pmksa, pmk, pmk_len, NULL,
NULL, 0, NULL, 0,
sm->preauth_bssid, sm->own_addr, sm->preauth_bssid, sm->own_addr,
sm->network_ctx, sm->network_ctx,

View file

@ -249,7 +249,7 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm,
!wpa_key_mgmt_suite_b(sm->key_mgmt) && !wpa_key_mgmt_suite_b(sm->key_mgmt) &&
!wpa_key_mgmt_ft(sm->key_mgmt)) { !wpa_key_mgmt_ft(sm->key_mgmt)) {
sa = pmksa_cache_add(sm->pmksa, sa = pmksa_cache_add(sm->pmksa,
sm->pmk, pmk_len, sm->pmk, pmk_len, NULL,
NULL, 0, NULL, 0,
src_addr, sm->own_addr, src_addr, sm->own_addr,
sm->network_ctx, sm->network_ctx,
@ -1297,7 +1297,7 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm,
if (sm->proto == WPA_PROTO_RSN && wpa_key_mgmt_suite_b(sm->key_mgmt)) { if (sm->proto == WPA_PROTO_RSN && wpa_key_mgmt_suite_b(sm->key_mgmt)) {
struct rsn_pmksa_cache_entry *sa; struct rsn_pmksa_cache_entry *sa;
sa = pmksa_cache_add(sm->pmksa, sm->pmk, sm->pmk_len, sa = pmksa_cache_add(sm->pmksa, sm->pmk, sm->pmk_len, NULL,
sm->ptk.kck, sm->ptk.kck_len, sm->ptk.kck, sm->ptk.kck_len,
sm->bssid, sm->own_addr, sm->bssid, sm->own_addr,
sm->network_ctx, sm->key_mgmt); sm->network_ctx, sm->key_mgmt);
@ -2391,12 +2391,13 @@ void wpa_sm_notify_disassoc(struct wpa_sm *sm)
* @sm: Pointer to WPA state machine data from wpa_sm_init() * @sm: Pointer to WPA state machine data from wpa_sm_init()
* @pmk: The new PMK * @pmk: The new PMK
* @pmk_len: The length of the new PMK in bytes * @pmk_len: The length of the new PMK in bytes
* @pmkid: Calculated PMKID
* @bssid: AA to add into PMKSA cache or %NULL to not cache the PMK * @bssid: AA to add into PMKSA cache or %NULL to not cache the PMK
* *
* Configure the PMK for WPA state machine. * 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) const u8 *pmkid, const u8 *bssid)
{ {
if (sm == NULL) if (sm == NULL)
return; return;
@ -2411,7 +2412,7 @@ void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len,
#endif /* CONFIG_IEEE80211R */ #endif /* CONFIG_IEEE80211R */
if (bssid) { if (bssid) {
pmksa_cache_add(sm->pmksa, pmk, pmk_len, NULL, 0, pmksa_cache_add(sm->pmksa, pmk, pmk_len, pmkid, NULL, 0,
bssid, sm->own_addr, bssid, sm->own_addr,
sm->network_ctx, sm->key_mgmt); sm->network_ctx, sm->key_mgmt);
} }

View file

@ -114,7 +114,7 @@ void wpa_sm_deinit(struct wpa_sm *sm);
void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid); void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid);
void wpa_sm_notify_disassoc(struct wpa_sm *sm); void wpa_sm_notify_disassoc(struct wpa_sm *sm);
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); const u8 *pmkid, const u8 *bssid);
void wpa_sm_set_pmk_from_pmksa(struct wpa_sm *sm); void wpa_sm_set_pmk_from_pmksa(struct wpa_sm *sm);
void wpa_sm_set_fast_reauth(struct wpa_sm *sm, int fast_reauth); void wpa_sm_set_fast_reauth(struct wpa_sm *sm, int fast_reauth);
void wpa_sm_set_scard_ctx(struct wpa_sm *sm, void *scard_ctx); void wpa_sm_set_scard_ctx(struct wpa_sm *sm, void *scard_ctx);
@ -181,7 +181,8 @@ static inline void wpa_sm_notify_disassoc(struct wpa_sm *sm)
} }
static inline void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, static inline void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk,
size_t pmk_len, const u8 *bssid) size_t pmk_len, const u8 *pmkid,
const u8 *bssid)
{ {
} }

View file

@ -230,7 +230,7 @@ static int ibss_rsn_supp_init(struct ibss_rsn_peer *peer, const u8 *own_addr,
wpa_sm_set_param(peer->supp, WPA_PARAM_PAIRWISE, WPA_CIPHER_CCMP); wpa_sm_set_param(peer->supp, WPA_PARAM_PAIRWISE, WPA_CIPHER_CCMP);
wpa_sm_set_param(peer->supp, WPA_PARAM_GROUP, WPA_CIPHER_CCMP); wpa_sm_set_param(peer->supp, WPA_PARAM_GROUP, WPA_CIPHER_CCMP);
wpa_sm_set_param(peer->supp, WPA_PARAM_KEY_MGMT, WPA_KEY_MGMT_PSK); wpa_sm_set_param(peer->supp, WPA_PARAM_KEY_MGMT, WPA_KEY_MGMT_PSK);
wpa_sm_set_pmk(peer->supp, psk, PMK_LEN, NULL); wpa_sm_set_pmk(peer->supp, psk, PMK_LEN, NULL, NULL);
peer->supp_ie_len = sizeof(peer->supp_ie); peer->supp_ie_len = sizeof(peer->supp_ie);
if (wpa_sm_set_assoc_wpa_ie_default(peer->supp, peer->supp_ie, if (wpa_sm_set_assoc_wpa_ie_default(peer->supp, peer->supp_ie,

View file

@ -814,7 +814,7 @@ void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data)
wpa_printf(MSG_DEBUG, "SME: SAE completed - setting PMK for " wpa_printf(MSG_DEBUG, "SME: SAE completed - setting PMK for "
"4-way handshake"); "4-way handshake");
wpa_sm_set_pmk(wpa_s->wpa, wpa_s->sme.sae.pmk, PMK_LEN, wpa_sm_set_pmk(wpa_s->wpa, wpa_s->sme.sae.pmk, PMK_LEN,
wpa_s->pending_bssid); wpa_s->sme.sae.pmkid, wpa_s->pending_bssid);
} }
#endif /* CONFIG_SAE */ #endif /* CONFIG_SAE */

View file

@ -1293,7 +1293,8 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
int psk_set = 0; int psk_set = 0;
if (ssid->psk_set) { if (ssid->psk_set) {
wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL); wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL,
NULL);
psk_set = 1; psk_set = 1;
} }
#ifndef CONFIG_NO_PBKDF2 #ifndef CONFIG_NO_PBKDF2
@ -1304,7 +1305,7 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
4096, psk, PMK_LEN); 4096, psk, PMK_LEN);
wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)", wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
psk, PMK_LEN); psk, PMK_LEN);
wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL); wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL, NULL);
psk_set = 1; psk_set = 1;
os_memset(psk, 0, sizeof(psk)); os_memset(psk, 0, sizeof(psk));
} }
@ -1342,7 +1343,8 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
wpa_hexdump_key(MSG_MSGDUMP, "PSK (from " wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
"external passphrase)", "external passphrase)",
psk, PMK_LEN); psk, PMK_LEN);
wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL); wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
NULL);
psk_set = 1; psk_set = 1;
os_memset(psk, 0, sizeof(psk)); os_memset(psk, 0, sizeof(psk));
} else } else
@ -1355,7 +1357,8 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
ext_password_free(pw); ext_password_free(pw);
return -1; return -1;
} }
wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL); wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
NULL);
psk_set = 1; psk_set = 1;
os_memset(psk, 0, sizeof(psk)); os_memset(psk, 0, sizeof(psk));
} else { } else {