FILS: Update PMKID derivation rules for ERP key hierarchy establishment

IEEE Std 802.11ai-2016 had missed a change in the Pairwise key hierarchy
clause (12.7.1.3 in IEEE Std 802.11-2016) and due to that, the previous
implementation ended up using HMAC-SHA-1 -based PMKID derivation. This
was not really the intent of the FILS design and that issue was fixed
during REVmd work with the changes proposed in
https://mentor.ieee.org/802.11/dcn/17/11-17-0906-04-000m-fils-fixes.docx
that change FILS cases to use HMAC-SHA-256 and HMAC-SHA-384 based on the
negotiated AKM.

Update the implementation to match the new design. This changes the
rsn_pmkid() function to take in the more generic AKMP identifier instead
of a boolean identifying whether SHA256 is used.

Note: This is not backwards compatible, i.e., this breaks PMKSA caching
based on the initial ERP key hierarchy setup if only STA or AP side
implementation is updated. PMKSA caching based on FILS authentication
exchange is not impacted by this, though.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Jouni Malinen 2017-09-13 17:58:29 +03:00 committed by Jouni Malinen
parent 3031133983
commit 41b8191485
5 changed files with 33 additions and 16 deletions

View file

@ -338,8 +338,7 @@ pmksa_cache_auth_create_entry(const u8 *pmk, size_t pmk_len, const u8 *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);
else else
rsn_pmkid(pmk, pmk_len, aa, spa, entry->pmkid, rsn_pmkid(pmk, pmk_len, aa, spa, entry->pmkid, akmp);
wpa_key_mgmt_sha256(akmp));
os_get_reltime(&now); os_get_reltime(&now);
entry->expiration = now.sec; entry->expiration = now.sec;
if (session_timeout > 0) if (session_timeout > 0)
@ -518,7 +517,7 @@ struct rsn_pmksa_cache_entry * pmksa_cache_get_okc(
if (os_memcmp(entry->spa, spa, ETH_ALEN) != 0) if (os_memcmp(entry->spa, spa, ETH_ALEN) != 0)
continue; continue;
rsn_pmkid(entry->pmk, entry->pmk_len, aa, spa, new_pmkid, rsn_pmkid(entry->pmk, entry->pmk_len, aa, spa, new_pmkid,
wpa_key_mgmt_sha256(entry->akmp)); entry->akmp);
if (os_memcmp(new_pmkid, pmkid, PMKID_LEN) == 0) if (os_memcmp(new_pmkid, pmkid, PMKID_LEN) == 0)
return entry; return entry;
} }

View file

@ -2085,7 +2085,7 @@ SM_STATE(WPA_PTK, PTKSTART)
*/ */
rsn_pmkid(sm->PMK, sm->pmk_len, sm->wpa_auth->addr, rsn_pmkid(sm->PMK, sm->pmk_len, sm->wpa_auth->addr,
sm->addr, &pmkid[2 + RSN_SELECTOR_LEN], sm->addr, &pmkid[2 + RSN_SELECTOR_LEN],
wpa_key_mgmt_sha256(sm->wpa_key_mgmt)); sm->wpa_key_mgmt);
} }
} }
wpa_send_eapol(sm->wpa_auth, sm, wpa_send_eapol(sm->wpa_auth, sm,

View file

@ -1428,29 +1428,48 @@ int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce,
* @aa: Authenticator address * @aa: Authenticator address
* @spa: Supplicant address * @spa: Supplicant address
* @pmkid: Buffer for PMKID * @pmkid: Buffer for PMKID
* @use_sha256: Whether to use SHA256-based KDF * @akmp: Negotiated key management protocol
* *
* IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy * IEEE Std 802.11-2016 - 12.7.1.3 Pairwise key hierarchy
* PMKID = HMAC-SHA1-128(PMK, "PMK Name" || AA || SPA) * AKM: 00-0F-AC:5, 00-0F-AC:6, 00-0F-AC:14, 00-0F-AC:16
* PMKID = Truncate-128(HMAC-SHA-256(PMK, "PMK Name" || AA || SPA))
* AKM: 00-0F-AC:11
* See rsn_pmkid_suite_b()
* AKM: 00-0F-AC:12
* See rsn_pmkid_suite_b_192()
* AKM: 00-0F-AC:15, 00-0F-AC:17
* PMKID = Truncate-128(HMAC-SHA-384(PMK, "PMK Name" || AA || SPA))
* Otherwise:
* PMKID = Truncate-128(HMAC-SHA-1(PMK, "PMK Name" || AA || SPA))
*/ */
void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa, void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa,
u8 *pmkid, int use_sha256) u8 *pmkid, int akmp)
{ {
char *title = "PMK Name"; char *title = "PMK Name";
const u8 *addr[3]; const u8 *addr[3];
const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN }; const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN };
unsigned char hash[SHA256_MAC_LEN]; unsigned char hash[SHA384_MAC_LEN];
addr[0] = (u8 *) title; addr[0] = (u8 *) title;
addr[1] = aa; addr[1] = aa;
addr[2] = spa; addr[2] = spa;
#ifdef CONFIG_IEEE80211W if (0) {
if (use_sha256) #ifdef CONFIG_FILS
} else if (wpa_key_mgmt_sha384(akmp)) {
wpa_printf(MSG_DEBUG, "RSN: Derive PMKID using HMAC-SHA-384");
hmac_sha384_vector(pmk, pmk_len, 3, addr, len, hash);
#endif /* CONFIG_FILS */
#if defined(CONFIG_IEEE80211W) || defined(CONFIG_FILS)
} else if (wpa_key_mgmt_sha256(akmp)) {
wpa_printf(MSG_DEBUG, "RSN: Derive PMKID using HMAC-SHA-256");
hmac_sha256_vector(pmk, pmk_len, 3, addr, len, hash); hmac_sha256_vector(pmk, pmk_len, 3, addr, len, hash);
else #endif /* CONFIG_IEEE80211W || CONFIG_FILS */
#endif /* CONFIG_IEEE80211W */ } else {
wpa_printf(MSG_DEBUG, "RSN: Derive PMKID using HMAC-SHA-1");
hmac_sha1_vector(pmk, pmk_len, 3, addr, len, hash); hmac_sha1_vector(pmk, pmk_len, 3, addr, len, hash);
}
wpa_hexdump(MSG_DEBUG, "RSN: Derived PMKID", hash, PMKID_LEN);
os_memcpy(pmkid, hash, PMKID_LEN); os_memcpy(pmkid, hash, PMKID_LEN);
} }

View file

@ -397,7 +397,7 @@ int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len,
struct wpa_ie_data *data); struct wpa_ie_data *data);
void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa, void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa,
u8 *pmkid, int use_sha256); u8 *pmkid, int akmp);
#ifdef CONFIG_SUITEB #ifdef CONFIG_SUITEB
int rsn_pmkid_suite_b(const u8 *kck, size_t kck_len, const u8 *aa, int rsn_pmkid_suite_b(const u8 *kck, size_t kck_len, const u8 *aa,
const u8 *spa, u8 *pmkid); const u8 *spa, u8 *pmkid);

View file

@ -154,8 +154,7 @@ pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
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);
else else
rsn_pmkid(pmk, pmk_len, aa, spa, entry->pmkid, rsn_pmkid(pmk, pmk_len, aa, spa, entry->pmkid, akmp);
wpa_key_mgmt_sha256(akmp));
os_get_reltime(&now); os_get_reltime(&now);
entry->expiration = now.sec + pmksa->sm->dot11RSNAConfigPMKLifetime; entry->expiration = now.sec + pmksa->sm->dot11RSNAConfigPMKLifetime;
entry->reauth_time = now.sec + pmksa->sm->dot11RSNAConfigPMKLifetime * entry->reauth_time = now.sec + pmksa->sm->dot11RSNAConfigPMKLifetime *