mirror of
https://github.com/vanhoefm/fragattacks.git
synced 2025-01-18 10:54:03 -05:00
OWE: Support DH groups 20 (NIST P-384) and 21 (NIST P-521) in station
This extends OWE support in wpa_supplicant to allow DH groups 20 and 21 to be used in addition to the mandatory group 19 (NIST P-256). The group is configured using the new network profile parameter owe_group. Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
7a12edd163
commit
ec9f483774
@ -16,6 +16,8 @@
|
|||||||
#include "crypto/random.h"
|
#include "crypto/random.h"
|
||||||
#include "crypto/aes_siv.h"
|
#include "crypto/aes_siv.h"
|
||||||
#include "crypto/sha256.h"
|
#include "crypto/sha256.h"
|
||||||
|
#include "crypto/sha384.h"
|
||||||
|
#include "crypto/sha512.h"
|
||||||
#include "common/ieee802_11_defs.h"
|
#include "common/ieee802_11_defs.h"
|
||||||
#include "common/ieee802_11_common.h"
|
#include "common/ieee802_11_common.h"
|
||||||
#include "eap_common/eap_defs.h"
|
#include "eap_common/eap_defs.h"
|
||||||
@ -4168,15 +4170,27 @@ int wpa_fils_is_completed(struct wpa_sm *sm)
|
|||||||
|
|
||||||
#ifdef CONFIG_OWE
|
#ifdef CONFIG_OWE
|
||||||
|
|
||||||
struct wpabuf * owe_build_assoc_req(struct wpa_sm *sm)
|
struct wpabuf * owe_build_assoc_req(struct wpa_sm *sm, u16 group)
|
||||||
{
|
{
|
||||||
struct wpabuf *ie = NULL, *pub = NULL;
|
struct wpabuf *ie = NULL, *pub = NULL;
|
||||||
|
size_t prime_len;
|
||||||
|
|
||||||
|
if (group == 19)
|
||||||
|
prime_len = 32;
|
||||||
|
else if (group == 20)
|
||||||
|
prime_len = 48;
|
||||||
|
else if (group == 21)
|
||||||
|
prime_len = 66;
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
|
||||||
crypto_ecdh_deinit(sm->owe_ecdh);
|
crypto_ecdh_deinit(sm->owe_ecdh);
|
||||||
sm->owe_ecdh = crypto_ecdh_init(OWE_DH_GROUP);
|
sm->owe_ecdh = crypto_ecdh_init(group);
|
||||||
if (!sm->owe_ecdh)
|
if (!sm->owe_ecdh)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
sm->owe_group = group;
|
||||||
pub = crypto_ecdh_get_pubkey(sm->owe_ecdh, 0);
|
pub = crypto_ecdh_get_pubkey(sm->owe_ecdh, 0);
|
||||||
|
pub = wpabuf_zeropad(pub, prime_len);
|
||||||
if (!pub)
|
if (!pub)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
@ -4186,7 +4200,7 @@ struct wpabuf * owe_build_assoc_req(struct wpa_sm *sm)
|
|||||||
wpabuf_put_u8(ie, WLAN_EID_EXTENSION);
|
wpabuf_put_u8(ie, WLAN_EID_EXTENSION);
|
||||||
wpabuf_put_u8(ie, 1 + 2 + wpabuf_len(pub));
|
wpabuf_put_u8(ie, 1 + 2 + wpabuf_len(pub));
|
||||||
wpabuf_put_u8(ie, WLAN_EID_EXT_OWE_DH_PARAM);
|
wpabuf_put_u8(ie, WLAN_EID_EXT_OWE_DH_PARAM);
|
||||||
wpabuf_put_le16(ie, OWE_DH_GROUP);
|
wpabuf_put_le16(ie, group);
|
||||||
wpabuf_put_buf(ie, pub);
|
wpabuf_put_buf(ie, pub);
|
||||||
wpabuf_free(pub);
|
wpabuf_free(pub);
|
||||||
wpa_hexdump_buf(MSG_DEBUG, "OWE: Diffie-Hellman Parameter element",
|
wpa_hexdump_buf(MSG_DEBUG, "OWE: Diffie-Hellman Parameter element",
|
||||||
@ -4208,10 +4222,11 @@ int owe_process_assoc_resp(struct wpa_sm *sm, const u8 *resp_ies,
|
|||||||
u16 group;
|
u16 group;
|
||||||
struct wpabuf *secret, *pub, *hkey;
|
struct wpabuf *secret, *pub, *hkey;
|
||||||
int res;
|
int res;
|
||||||
u8 prk[SHA256_MAC_LEN], pmkid[SHA256_MAC_LEN];
|
u8 prk[SHA512_MAC_LEN], pmkid[SHA512_MAC_LEN];
|
||||||
const char *info = "OWE Key Generation";
|
const char *info = "OWE Key Generation";
|
||||||
const u8 *addr[2];
|
const u8 *addr[2];
|
||||||
size_t len[2];
|
size_t len[2];
|
||||||
|
size_t hash_len, prime_len;
|
||||||
|
|
||||||
if (!resp_ies ||
|
if (!resp_ies ||
|
||||||
ieee802_11_parse_elems(resp_ies, resp_ies_len, &elems, 1) ==
|
ieee802_11_parse_elems(resp_ies, resp_ies_len, &elems, 1) ==
|
||||||
@ -4223,7 +4238,7 @@ int owe_process_assoc_resp(struct wpa_sm *sm, const u8 *resp_ies,
|
|||||||
}
|
}
|
||||||
|
|
||||||
group = WPA_GET_LE16(elems.owe_dh);
|
group = WPA_GET_LE16(elems.owe_dh);
|
||||||
if (group != OWE_DH_GROUP) {
|
if (group != sm->owe_group) {
|
||||||
wpa_printf(MSG_INFO,
|
wpa_printf(MSG_INFO,
|
||||||
"OWE: Unexpected Diffie-Hellman group in response: %u",
|
"OWE: Unexpected Diffie-Hellman group in response: %u",
|
||||||
group);
|
group);
|
||||||
@ -4235,9 +4250,19 @@ int owe_process_assoc_resp(struct wpa_sm *sm, const u8 *resp_ies,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (group == 19)
|
||||||
|
prime_len = 32;
|
||||||
|
else if (group == 20)
|
||||||
|
prime_len = 48;
|
||||||
|
else if (group == 21)
|
||||||
|
prime_len = 66;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
|
||||||
secret = crypto_ecdh_set_peerkey(sm->owe_ecdh, 0,
|
secret = crypto_ecdh_set_peerkey(sm->owe_ecdh, 0,
|
||||||
elems.owe_dh + 2,
|
elems.owe_dh + 2,
|
||||||
elems.owe_dh_len - 2);
|
elems.owe_dh_len - 2);
|
||||||
|
secret = wpabuf_zeropad(secret, prime_len);
|
||||||
if (!secret) {
|
if (!secret) {
|
||||||
wpa_printf(MSG_DEBUG, "OWE: Invalid peer DH public key");
|
wpa_printf(MSG_DEBUG, "OWE: Invalid peer DH public key");
|
||||||
return -1;
|
return -1;
|
||||||
@ -4257,8 +4282,21 @@ int owe_process_assoc_resp(struct wpa_sm *sm, const u8 *resp_ies,
|
|||||||
len[0] = wpabuf_len(pub);
|
len[0] = wpabuf_len(pub);
|
||||||
addr[1] = elems.owe_dh + 2;
|
addr[1] = elems.owe_dh + 2;
|
||||||
len[1] = elems.owe_dh_len - 2;
|
len[1] = elems.owe_dh_len - 2;
|
||||||
res = sha256_vector(2, addr, len, pmkid);
|
if (group == 19) {
|
||||||
if (res < 0) {
|
res = sha256_vector(2, addr, len, pmkid);
|
||||||
|
hash_len = SHA256_MAC_LEN;
|
||||||
|
} else if (group == 20) {
|
||||||
|
res = sha384_vector(2, addr, len, pmkid);
|
||||||
|
hash_len = SHA384_MAC_LEN;
|
||||||
|
} else if (group == 21) {
|
||||||
|
res = sha512_vector(2, addr, len, pmkid);
|
||||||
|
hash_len = SHA512_MAC_LEN;
|
||||||
|
} else {
|
||||||
|
res = -1;
|
||||||
|
hash_len = 0;
|
||||||
|
}
|
||||||
|
pub = wpabuf_zeropad(pub, prime_len);
|
||||||
|
if (res < 0 || !pub) {
|
||||||
wpabuf_free(pub);
|
wpabuf_free(pub);
|
||||||
wpabuf_clear_free(secret);
|
wpabuf_clear_free(secret);
|
||||||
return -1;
|
return -1;
|
||||||
@ -4274,26 +4312,40 @@ int owe_process_assoc_resp(struct wpa_sm *sm, const u8 *resp_ies,
|
|||||||
wpabuf_put_buf(hkey, pub); /* C */
|
wpabuf_put_buf(hkey, pub); /* C */
|
||||||
wpabuf_free(pub);
|
wpabuf_free(pub);
|
||||||
wpabuf_put_data(hkey, elems.owe_dh + 2, elems.owe_dh_len - 2); /* A */
|
wpabuf_put_data(hkey, elems.owe_dh + 2, elems.owe_dh_len - 2); /* A */
|
||||||
wpabuf_put_le16(hkey, OWE_DH_GROUP); /* group */
|
wpabuf_put_le16(hkey, sm->owe_group); /* group */
|
||||||
res = hmac_sha256(wpabuf_head(hkey), wpabuf_len(hkey),
|
if (group == 19)
|
||||||
wpabuf_head(secret), wpabuf_len(secret), prk);
|
res = hmac_sha256(wpabuf_head(hkey), wpabuf_len(hkey),
|
||||||
|
wpabuf_head(secret), wpabuf_len(secret), prk);
|
||||||
|
else if (group == 20)
|
||||||
|
res = hmac_sha384(wpabuf_head(hkey), wpabuf_len(hkey),
|
||||||
|
wpabuf_head(secret), wpabuf_len(secret), prk);
|
||||||
|
else if (group == 21)
|
||||||
|
res = hmac_sha512(wpabuf_head(hkey), wpabuf_len(hkey),
|
||||||
|
wpabuf_head(secret), wpabuf_len(secret), prk);
|
||||||
wpabuf_clear_free(hkey);
|
wpabuf_clear_free(hkey);
|
||||||
wpabuf_clear_free(secret);
|
wpabuf_clear_free(secret);
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
wpa_hexdump_key(MSG_DEBUG, "OWE: prk", prk, SHA256_MAC_LEN);
|
wpa_hexdump_key(MSG_DEBUG, "OWE: prk", prk, hash_len);
|
||||||
|
|
||||||
/* PMK = HKDF-expand(prk, "OWE Key Generation", n) */
|
/* PMK = HKDF-expand(prk, "OWE Key Generation", n) */
|
||||||
|
|
||||||
res = hmac_sha256_kdf(prk, SHA256_MAC_LEN, NULL, (const u8 *) info,
|
if (group == 19)
|
||||||
os_strlen(info), sm->pmk, PMK_LEN);
|
res = hmac_sha256_kdf(prk, hash_len, NULL, (const u8 *) info,
|
||||||
os_memset(prk, 0, SHA256_MAC_LEN);
|
os_strlen(info), sm->pmk, hash_len);
|
||||||
|
else if (group == 20)
|
||||||
|
res = hmac_sha384_kdf(prk, hash_len, NULL, (const u8 *) info,
|
||||||
|
os_strlen(info), sm->pmk, hash_len);
|
||||||
|
else if (group == 21)
|
||||||
|
res = hmac_sha512_kdf(prk, hash_len, NULL, (const u8 *) info,
|
||||||
|
os_strlen(info), sm->pmk, hash_len);
|
||||||
|
os_memset(prk, 0, SHA512_MAC_LEN);
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
return -1;
|
return -1;
|
||||||
sm->pmk_len = PMK_LEN;
|
sm->pmk_len = hash_len;
|
||||||
|
|
||||||
wpa_hexdump_key(MSG_DEBUG, "OWE: PMK", sm->pmk, PMK_LEN);
|
wpa_hexdump_key(MSG_DEBUG, "OWE: PMK", sm->pmk, sm->pmk_len);
|
||||||
wpa_hexdump(MSG_DEBUG, "OWE: PMKID", pmkid, PMKID_LEN);
|
wpa_hexdump(MSG_DEBUG, "OWE: PMKID", pmkid, PMKID_LEN);
|
||||||
/* TODO: Add PMKSA cache entry */
|
/* TODO: Add PMKSA cache entry */
|
||||||
|
|
||||||
|
@ -457,7 +457,7 @@ struct wpabuf * fils_build_assoc_req(struct wpa_sm *sm, const u8 **kek,
|
|||||||
unsigned int num_hlp);
|
unsigned int num_hlp);
|
||||||
int fils_process_assoc_resp(struct wpa_sm *sm, const u8 *resp, size_t len);
|
int fils_process_assoc_resp(struct wpa_sm *sm, const u8 *resp, size_t len);
|
||||||
|
|
||||||
struct wpabuf * owe_build_assoc_req(struct wpa_sm *sm);
|
struct wpabuf * owe_build_assoc_req(struct wpa_sm *sm, u16 group);
|
||||||
int owe_process_assoc_resp(struct wpa_sm *sm, const u8 *resp_ies,
|
int owe_process_assoc_resp(struct wpa_sm *sm, const u8 *resp_ies,
|
||||||
size_t resp_ies_len);
|
size_t resp_ies_len);
|
||||||
|
|
||||||
|
@ -161,6 +161,7 @@ struct wpa_sm {
|
|||||||
|
|
||||||
#ifdef CONFIG_OWE
|
#ifdef CONFIG_OWE
|
||||||
struct crypto_ecdh *owe_ecdh;
|
struct crypto_ecdh *owe_ecdh;
|
||||||
|
u16 owe_group;
|
||||||
#endif /* CONFIG_OWE */
|
#endif /* CONFIG_OWE */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -263,6 +263,11 @@ ifdef CONFIG_OWE
|
|||||||
L_CFLAGS += -DCONFIG_OWE
|
L_CFLAGS += -DCONFIG_OWE
|
||||||
NEED_ECC=y
|
NEED_ECC=y
|
||||||
NEED_HMAC_SHA256_KDF=y
|
NEED_HMAC_SHA256_KDF=y
|
||||||
|
NEED_HMAC_SHA384_KDF=y
|
||||||
|
NEED_HMAC_SHA512_KDF=y
|
||||||
|
NEED_SHA256=y
|
||||||
|
NEED_SHA384=y
|
||||||
|
NEED_SHA512=y
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef CONFIG_FILS
|
ifdef CONFIG_FILS
|
||||||
|
@ -296,6 +296,11 @@ ifdef CONFIG_OWE
|
|||||||
CFLAGS += -DCONFIG_OWE
|
CFLAGS += -DCONFIG_OWE
|
||||||
NEED_ECC=y
|
NEED_ECC=y
|
||||||
NEED_HMAC_SHA256_KDF=y
|
NEED_HMAC_SHA256_KDF=y
|
||||||
|
NEED_HMAC_SHA384_KDF=y
|
||||||
|
NEED_HMAC_SHA512_KDF=y
|
||||||
|
NEED_SHA256=y
|
||||||
|
NEED_SHA384=y
|
||||||
|
NEED_SHA512=y
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef CONFIG_FILS
|
ifdef CONFIG_FILS
|
||||||
|
@ -2281,6 +2281,7 @@ static const struct parse_data ssid_fields[] = {
|
|||||||
{ STR_LEN(dpp_csign) },
|
{ STR_LEN(dpp_csign) },
|
||||||
{ INT(dpp_csign_expiry) },
|
{ INT(dpp_csign_expiry) },
|
||||||
#endif /* CONFIG_DPP */
|
#endif /* CONFIG_DPP */
|
||||||
|
{ INT_RANGE(owe_group, 0, 65535) },
|
||||||
};
|
};
|
||||||
|
|
||||||
#undef OFFSET
|
#undef OFFSET
|
||||||
|
@ -873,6 +873,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
|
|||||||
STR(dpp_csign);
|
STR(dpp_csign);
|
||||||
INT(dpp_csign_expiry);
|
INT(dpp_csign_expiry);
|
||||||
#endif /* CONFIG_DPP */
|
#endif /* CONFIG_DPP */
|
||||||
|
INT(owe_group);
|
||||||
#ifdef CONFIG_HT_OVERRIDES
|
#ifdef CONFIG_HT_OVERRIDES
|
||||||
INT_DEF(disable_ht, DEFAULT_DISABLE_HT);
|
INT_DEF(disable_ht, DEFAULT_DISABLE_HT);
|
||||||
INT_DEF(disable_ht40, DEFAULT_DISABLE_HT40);
|
INT_DEF(disable_ht40, DEFAULT_DISABLE_HT40);
|
||||||
|
@ -893,6 +893,17 @@ struct wpa_ssid {
|
|||||||
* 0 indicates no expiration.
|
* 0 indicates no expiration.
|
||||||
*/
|
*/
|
||||||
unsigned int dpp_csign_expiry;
|
unsigned int dpp_csign_expiry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* owe_group - OWE DH Group
|
||||||
|
*
|
||||||
|
* 0 = use default (19)
|
||||||
|
* 1-65535 DH Group to use for OWE
|
||||||
|
*
|
||||||
|
* Groups 19 (NIST P-256), 20 (NIST P-384), and 21 (NIST P-521) are
|
||||||
|
* currently supported.
|
||||||
|
*/
|
||||||
|
int owe_group;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* CONFIG_SSID_H */
|
#endif /* CONFIG_SSID_H */
|
||||||
|
@ -1195,8 +1195,11 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode,
|
|||||||
if (auth_type == WLAN_AUTH_OPEN &&
|
if (auth_type == WLAN_AUTH_OPEN &&
|
||||||
wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
|
wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
|
||||||
struct wpabuf *owe_ie;
|
struct wpabuf *owe_ie;
|
||||||
|
u16 group = OWE_DH_GROUP;
|
||||||
|
|
||||||
owe_ie = owe_build_assoc_req(wpa_s->wpa);
|
if (wpa_s->current_ssid && wpa_s->current_ssid->owe_group)
|
||||||
|
group = wpa_s->current_ssid->owe_group;
|
||||||
|
owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
|
||||||
if (!owe_ie) {
|
if (!owe_ie) {
|
||||||
wpa_printf(MSG_ERROR,
|
wpa_printf(MSG_ERROR,
|
||||||
"OWE: Failed to build IE for Association Request frame");
|
"OWE: Failed to build IE for Association Request frame");
|
||||||
|
Loading…
Reference in New Issue
Block a user