Skip to content

Commit 24de52e

Browse files
ShyamalKhachaneespressif-bot
authored andcommitted
fix(esp_wifi): Handle PMKID mismatch or absence in OWE
Compute keys incase PMKID does not match or PMKID is absent in association response
1 parent b58fa75 commit 24de52e

File tree

1 file changed

+95
-86
lines changed
  • components/wpa_supplicant/src/rsn_supp

1 file changed

+95
-86
lines changed

components/wpa_supplicant/src/rsn_supp/wpa.c

Lines changed: 95 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -2868,7 +2868,8 @@ int owe_process_assoc_resp(const u8 *rsn_ie, size_t rsn_len, const uint8_t *dh_i
28682868
struct wpa_sm *sm;
28692869
sm = get_wpa_sm();
28702870

2871-
wpabuf_free(sm->owe_ie); //free the dh ie constructed in owe_build_assoc_req
2871+
/* Deallocate the dh ie buffer constructed in owe_build_assoc_req */
2872+
wpabuf_free(sm->owe_ie);
28722873
sm->owe_ie = NULL;
28732874

28742875
struct wpa_ie_data *parsed_rsn_data;
@@ -2882,121 +2883,129 @@ int owe_process_assoc_resp(const u8 *rsn_ie, size_t rsn_len, const uint8_t *dh_i
28822883
goto fail;
28832884
}
28842885

2886+
if (!dh_ie && parsed_rsn_data->num_pmkid == 0) {
2887+
wpa_printf(MSG_ERROR, "OWE: Assoc response should either have pmkid or DH IE");
2888+
goto fail;
2889+
}
2890+
2891+
/* Check for PMK caching */
2892+
if (sm->cur_pmksa && parsed_rsn_data && parsed_rsn_data->num_pmkid == 1 && parsed_rsn_data->pmkid) {
2893+
if (os_memcmp(parsed_rsn_data->pmkid, sm->cur_pmksa->pmkid, OWE_PMKID_LEN) == 0) {
2894+
wpa_printf(MSG_DEBUG, "OWE: Using PMK caching");
2895+
wpa_sm_set_pmk_from_pmksa(sm);
2896+
goto done;
2897+
} else {
2898+
/* If PMKID mismatches, derive keys again */
2899+
wpa_printf(MSG_DEBUG, "OWE : Invalid PMKID in response");
2900+
}
2901+
}
2902+
2903+
if (dh_ie == NULL) {
2904+
wpa_printf(MSG_ERROR, "OWE: No Diffie Hellman IE in association response");
2905+
goto fail;
2906+
}
28852907
if (dh_ie && MIN_DH_LEN(dh_len)) {
28862908
wpa_printf(MSG_ERROR, "OWE: Invalid Diffie Hellman IE");
28872909
goto fail;
28882910
}
2889-
if (!dh_ie && parsed_rsn_data->num_pmkid == 0) {
2890-
wpa_printf(MSG_ERROR, "OWE: Assoc response should either have pmkid or DH IE");
2911+
2912+
/* If STA or AP does not have PMKID, or PMKID mismatches, proceed with normal association */
2913+
dh_len += 2;
2914+
2915+
dh_ie += 3;
2916+
dh_len -=3;
2917+
group = WPA_GET_LE16(dh_ie);
2918+
2919+
/* Only group 19 is supported */
2920+
if ((group != sm->owe_group) || (group != OWE_DH_GRP19)) {
2921+
wpa_printf(MSG_ERROR, "OWE: Unexpected Diffie-Hellman group in response");
28912922
goto fail;
28922923
}
28932924

2894-
if (!sm->cur_pmksa) { /* No PMK caching */
2895-
if (dh_ie == NULL) {
2896-
goto fail;
2897-
}
2898-
dh_len += 2;
2925+
prime_len = OWE_PRIME_LEN;
28992926

2900-
dh_ie += 3;
2901-
dh_len -=3;
2902-
group = WPA_GET_LE16(dh_ie);
2927+
/* Set peer's public key point and calculate shared secret */
2928+
sh_secret = crypto_ecdh_set_peerkey(sm->owe_ecdh, 0, dh_ie+2, dh_len-2);
2929+
sh_secret = wpabuf_zeropad(sh_secret, prime_len);
2930+
if (!sh_secret) {
2931+
wpa_printf(MSG_ERROR, "OWE: Invalid peer DH public key");
2932+
goto fail;
2933+
}
29032934

2904-
/* Only group 19 is supported */
2905-
if ((group != sm->owe_group) || (group != OWE_DH_GRP19)) {
2906-
wpa_printf(MSG_ERROR, "OWE: Unexpected Diffie-Hellman group in response");
2907-
goto fail;
2908-
}
2935+
wpa_hexdump_buf_key(MSG_DEBUG, "OWE: DH shared secret", sh_secret);
2936+
pub = crypto_ecdh_get_pubkey(sm->owe_ecdh, 0);
2937+
if (!pub) {
2938+
wpa_printf(MSG_ERROR, "No own public key");
2939+
goto fail;
2940+
}
29092941

2910-
prime_len = OWE_PRIME_LEN;
2942+
/* PMKID = Truncate-128(Hash(C | A)) */
2943+
addr[0] = wpabuf_head(pub);
2944+
len[0] = wpabuf_len(pub);
2945+
addr[1] = dh_ie + 2;
2946+
len[1] = dh_len - 2;
29112947

2912-
/* Set peer's public key point and calculate shared secret */
2913-
sh_secret = crypto_ecdh_set_peerkey(sm->owe_ecdh, 0, dh_ie+2, dh_len-2);
2914-
sh_secret = wpabuf_zeropad(sh_secret, prime_len);
2915-
if (!sh_secret) {
2916-
wpa_printf(MSG_ERROR, "OWE: Invalid peer DH public key");
2917-
goto fail;
2918-
}
2948+
int res = sha256_vector(2, addr, len, pmkid);
2949+
if (res < 0 ) {
2950+
goto fail;
2951+
}
29192952

2920-
wpa_hexdump_buf_key(MSG_DEBUG, "OWE: DH shared secret", sh_secret);
2921-
pub = crypto_ecdh_get_pubkey(sm->owe_ecdh, 0);
2922-
if (!pub) {
2923-
wpa_printf(MSG_ERROR, "No own public key");
2924-
wpabuf_free(sh_secret);
2925-
goto fail;
2926-
}
2953+
hash_len = SHA256_MAC_LEN;
29272954

2928-
/* PMKID = Truncate-128(Hash(C | A)) */
2929-
addr[0] = wpabuf_head(pub);
2930-
len[0] = wpabuf_len(pub);
2931-
addr[1] = dh_ie + 2;
2932-
len[1] = dh_len - 2;
2955+
pub = wpabuf_zeropad(pub, prime_len);
2956+
if (!pub) {
2957+
goto fail;
2958+
}
29332959

2934-
int res = sha256_vector(2, addr, len, pmkid);
2935-
if (res < 0 ) {
2936-
goto fail;
2937-
}
2960+
/* prk = HKDF-extract(C | A | group, z) */
2961+
hkey = wpabuf_alloc(wpabuf_len(pub) + dh_len - 2 + 2);
2962+
if (!hkey) {
2963+
goto fail;
2964+
}
29382965

2939-
hash_len = SHA256_MAC_LEN;
2966+
wpabuf_put_buf(hkey, pub); /* C */
2967+
wpabuf_free(pub);
29402968

2941-
pub = wpabuf_zeropad(pub, prime_len);
2969+
wpabuf_put_data(hkey, dh_ie + 2, dh_len - 2); /* A */
2970+
wpabuf_put_le16(hkey, sm->owe_group); /* group */
29422971

2943-
/* prk = HKDF-extract(C | A | group, z) */
2944-
hkey = wpabuf_alloc(wpabuf_len(pub) + dh_len - 2 + 2);
2972+
res = hmac_sha256(wpabuf_head(hkey), wpabuf_len(hkey), wpabuf_head(sh_secret), wpabuf_len(sh_secret), prk);
2973+
if (res < 0 ) {
2974+
goto fail;
2975+
}
29452976

2946-
wpabuf_put_buf(hkey, pub); /* C */
2947-
wpabuf_free(pub);
2977+
hash_len = SHA256_MAC_LEN;
29482978

2949-
wpabuf_put_data(hkey, dh_ie + 2, dh_len - 2); /* A */
2950-
wpabuf_put_le16(hkey, sm->owe_group); /* group */
2979+
wpabuf_free(hkey);
2980+
wpabuf_clear_free(sh_secret);
29512981

2952-
res = hmac_sha256(wpabuf_head(hkey), wpabuf_len(hkey), wpabuf_head(sh_secret), wpabuf_len(sh_secret), prk);
2953-
if (res < 0 ) {
2954-
goto fail;
2955-
}
2982+
wpa_hexdump_key(MSG_DEBUG, "OWE: prk", prk, hash_len);
29562983

2957-
hash_len = SHA256_MAC_LEN;
2984+
/* PMK = HKDF-expand(prk, "OWE Key Generation", n) */
2985+
res = hmac_sha256_kdf(prk, hash_len, NULL, (const u8 *)info,
2986+
os_strlen(info), pmk, hash_len);
2987+
if (res < 0 ) {
2988+
goto fail;
2989+
}
29582990

2959-
wpabuf_free(hkey);
2960-
wpabuf_free(sh_secret);
2991+
forced_memzero(prk, SHA256_MAC_LEN);
2992+
wpa_hexdump(MSG_DEBUG, "OWE: PMKID", pmkid, OWE_PMKID_LEN);
29612993

2962-
wpa_hexdump_key(MSG_DEBUG, "OWE: prk", prk, hash_len);
2994+
os_memcpy(sm->pmk,pmk,hash_len);
2995+
sm->pmk_len = hash_len;
2996+
wpa_hexdump_key(MSG_DEBUG, "OWE: PMK", sm->pmk, sm->pmk_len);
29632997

2964-
/* PMK = HKDF-expand(prk, "OWE Key Generation", n) */
2965-
res = hmac_sha256_kdf(prk, hash_len, NULL, (const u8 *)info,
2966-
os_strlen(info), pmk, hash_len);
2967-
if (res < 0 ) {
2968-
goto fail;
2969-
}
2998+
pmksa_cache_add(sm->pmksa, sm->pmk, sm->pmk_len, pmkid, NULL, 0,
2999+
sm->bssid, sm->own_addr, sm->network_ctx, sm->key_mgmt);
29703000

2971-
forced_memzero(prk, SHA256_MAC_LEN);
2972-
wpa_hexdump(MSG_DEBUG, "OWE: PMKID", pmkid, OWE_PMKID_LEN);
2973-
2974-
os_memcpy(sm->pmk,pmk,hash_len);
2975-
sm->pmk_len = hash_len;
2976-
wpa_hexdump_key(MSG_DEBUG, "OWE: PMK", sm->pmk, sm->pmk_len);
2977-
2978-
pmksa_cache_add(sm->pmksa, sm->pmk, sm->pmk_len, pmkid, NULL, 0,
2979-
sm->bssid, sm->own_addr, sm->network_ctx, sm->key_mgmt);
2980-
goto done;
2981-
} else { /* PMK caching */
2982-
if (parsed_rsn_data && sm->cur_pmksa) {
2983-
if (parsed_rsn_data->num_pmkid == 1 && parsed_rsn_data->pmkid) {
2984-
if (os_memcmp(parsed_rsn_data->pmkid, sm->cur_pmksa->pmkid, OWE_PMKID_LEN) == 0) {
2985-
wpa_printf(MSG_DEBUG, "OWE: Using PMK caching");
2986-
wpa_sm_set_pmk_from_pmksa(sm);
2987-
goto done;
2988-
} else {
2989-
wpa_printf(MSG_DEBUG, "OWE : Invalid PMKID in response");
2990-
goto fail;
2991-
}
2992-
}
2993-
}
2994-
}
29953001
done:
29963002
os_free(parsed_rsn_data);
29973003
return 0;
29983004
fail:
29993005
os_free(parsed_rsn_data);
3006+
wpabuf_free(pub);
3007+
wpabuf_free(hkey);
3008+
wpabuf_clear_free(sh_secret);
30003009
return -1;
30013010
}
30023011
#endif // CONFIG_OWE_STA

0 commit comments

Comments
 (0)