aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Malinen <jouni@qca.qualcomm.com>2017-10-08 13:37:32 (GMT)
committerJouni Malinen <j@w1.fi>2017-10-08 14:12:35 (GMT)
commit7a12edd163ff0e50b9c89ce0407577da500299af (patch)
tree8a71a75addbf41b80cfbab6def317c8e04e43b01
parent6c4726189c5844fe39e3be0d4f1206ba8b4c8c36 (diff)
downloadhostap-7a12edd163ff0e50b9c89ce0407577da500299af.zip
hostap-7a12edd163ff0e50b9c89ce0407577da500299af.tar.gz
hostap-7a12edd163ff0e50b9c89ce0407577da500299af.tar.bz2
OWE: Support DH groups 20 (NIST P-384) and 21 (NIST P-521) in AP mode
This extends OWE support in hostapd to allow DH groups 20 and 21 to be used in addition to the mandatory group 19 (NIST P-256). Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
-rw-r--r--hostapd/Android.mk5
-rw-r--r--hostapd/Makefile5
-rw-r--r--src/ap/ieee802_11.c76
-rw-r--r--src/ap/sta_info.c2
-rw-r--r--src/ap/sta_info.h2
-rw-r--r--src/ap/wpa_auth.c25
-rw-r--r--src/ap/wpa_auth.h2
-rw-r--r--src/ap/wpa_auth_ft.c2
-rw-r--r--src/ap/wpa_auth_glue.c10
-rw-r--r--wpa_supplicant/ibss_rsn.c6
-rw-r--r--wpa_supplicant/mesh_rsn.c5
11 files changed, 104 insertions, 36 deletions
diff --git a/hostapd/Android.mk b/hostapd/Android.mk
index 0e781a3..a1153b3 100644
--- a/hostapd/Android.mk
+++ b/hostapd/Android.mk
@@ -274,6 +274,11 @@ ifdef CONFIG_OWE
L_CFLAGS += -DCONFIG_OWE
NEED_ECC=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
ifdef CONFIG_FILS
diff --git a/hostapd/Makefile b/hostapd/Makefile
index c54de39..a00e11c 100644
--- a/hostapd/Makefile
+++ b/hostapd/Makefile
@@ -318,6 +318,11 @@ ifdef CONFIG_OWE
CFLAGS += -DCONFIG_OWE
NEED_ECC=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
ifdef CONFIG_FILS
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index e4daec2..25d8e3b 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -14,6 +14,8 @@
#include "utils/eloop.h"
#include "crypto/crypto.h"
#include "crypto/sha256.h"
+#include "crypto/sha384.h"
+#include "crypto/sha512.h"
#include "crypto/random.h"
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
@@ -2131,21 +2133,32 @@ static u16 owe_process_assoc_req(struct sta_info *sta, const u8 *owe_dh,
{
struct wpabuf *secret, *pub, *hkey;
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 u8 *addr[2];
size_t len[2];
-
- if (WPA_GET_LE16(owe_dh) != OWE_DH_GROUP)
+ u16 group;
+ size_t hash_len, prime_len;
+
+ group = WPA_GET_LE16(owe_dh);
+ if (group == 19)
+ prime_len = 32;
+ else if (group == 20)
+ prime_len = 48;
+ else if (group == 21)
+ prime_len = 66;
+ else
return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
crypto_ecdh_deinit(sta->owe_ecdh);
- sta->owe_ecdh = crypto_ecdh_init(OWE_DH_GROUP);
+ sta->owe_ecdh = crypto_ecdh_init(group);
if (!sta->owe_ecdh)
return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
+ sta->owe_group = group;
secret = crypto_ecdh_set_peerkey(sta->owe_ecdh, 0, owe_dh + 2,
owe_dh_len - 2);
+ secret = wpabuf_zeropad(secret, prime_len);
if (!secret) {
wpa_printf(MSG_DEBUG, "OWE: Invalid peer DH public key");
return WLAN_STATUS_UNSPECIFIED_FAILURE;
@@ -2165,8 +2178,22 @@ static u16 owe_process_assoc_req(struct sta_info *sta, const u8 *owe_dh,
len[0] = owe_dh_len - 2;
addr[1] = wpabuf_head(pub);
len[1] = wpabuf_len(pub);
- res = sha256_vector(2, addr, len, pmkid);
- if (res < 0) {
+ if (group == 19) {
+ 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 {
+ wpabuf_free(pub);
+ wpabuf_clear_free(secret);
+ return WLAN_STATUS_UNSPECIFIED_FAILURE;
+ }
+ pub = wpabuf_zeropad(pub, prime_len);
+ if (res < 0 || !pub) {
wpabuf_free(pub);
wpabuf_clear_free(secret);
return WLAN_STATUS_UNSPECIFIED_FAILURE;
@@ -2182,35 +2209,50 @@ static u16 owe_process_assoc_req(struct sta_info *sta, const u8 *owe_dh,
wpabuf_put_data(hkey, owe_dh + 2, owe_dh_len - 2); /* C */
wpabuf_put_buf(hkey, pub); /* A */
wpabuf_free(pub);
- wpabuf_put_le16(hkey, OWE_DH_GROUP); /* group */
- res = hmac_sha256(wpabuf_head(hkey), wpabuf_len(hkey),
- wpabuf_head(secret), wpabuf_len(secret), prk);
+ wpabuf_put_le16(hkey, group); /* group */
+ if (group == 19)
+ 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(secret);
if (res < 0)
return WLAN_STATUS_UNSPECIFIED_FAILURE;
- 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) */
os_free(sta->owe_pmk);
- sta->owe_pmk = os_malloc(PMK_LEN);
+ sta->owe_pmk = os_malloc(hash_len);
if (!sta->owe_pmk) {
- os_memset(prk, 0, SHA256_MAC_LEN);
+ os_memset(prk, 0, SHA512_MAC_LEN);
return WLAN_STATUS_UNSPECIFIED_FAILURE;
}
- res = hmac_sha256_kdf(prk, SHA256_MAC_LEN, NULL, (const u8 *) info,
- os_strlen(info), sta->owe_pmk, PMK_LEN);
- os_memset(prk, 0, SHA256_MAC_LEN);
+ if (group == 19)
+ res = hmac_sha256_kdf(prk, hash_len, NULL, (const u8 *) info,
+ os_strlen(info), sta->owe_pmk, hash_len);
+ else if (group == 20)
+ res = hmac_sha384_kdf(prk, hash_len, NULL, (const u8 *) info,
+ os_strlen(info), sta->owe_pmk, hash_len);
+ else if (group == 21)
+ res = hmac_sha512_kdf(prk, hash_len, NULL, (const u8 *) info,
+ os_strlen(info), sta->owe_pmk, hash_len);
+ os_memset(prk, 0, SHA512_MAC_LEN);
if (res < 0) {
os_free(sta->owe_pmk);
sta->owe_pmk = NULL;
return WLAN_STATUS_UNSPECIFIED_FAILURE;
}
+ sta->owe_pmk_len = hash_len;
- wpa_hexdump_key(MSG_DEBUG, "OWE: PMK", sta->owe_pmk, PMK_LEN);
+ wpa_hexdump_key(MSG_DEBUG, "OWE: PMK", sta->owe_pmk, sta->owe_pmk_len);
wpa_hexdump(MSG_DEBUG, "OWE: PMKID", pmkid, PMKID_LEN);
/* TODO: Add PMKSA cache entry */
@@ -2822,7 +2864,7 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
*p++ = WLAN_EID_EXTENSION; /* Element ID */
*p++ = 1 + 2 + wpabuf_len(pub); /* Length */
*p++ = WLAN_EID_EXT_OWE_DH_PARAM; /* Element ID Extension */
- WPA_PUT_LE16(p, OWE_DH_GROUP);
+ WPA_PUT_LE16(p, sta->owe_group);
p += 2;
os_memcpy(p, wpabuf_head(pub), wpabuf_len(pub));
p += wpabuf_len(pub);
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index 1e21282..b1fde3c 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -353,7 +353,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
#endif /* CONFIG_FILS */
#ifdef CONFIG_OWE
- bin_clear_free(sta->owe_pmk, PMK_LEN);
+ bin_clear_free(sta->owe_pmk, sta->owe_pmk_len);
crypto_ecdh_deinit(sta->owe_ecdh);
#endif /* CONFIG_OWE */
diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
index 271128b..efbbceb 100644
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -246,7 +246,9 @@ struct sta_info {
#ifdef CONFIG_OWE
u8 *owe_pmk;
+ size_t owe_pmk_len;
struct crypto_ecdh *owe_ecdh;
+ u16 owe_group;
#endif /* CONFIG_OWE */
};
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index aca687c..5a37a09 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -110,12 +110,12 @@ static inline int wpa_auth_get_eapol(struct wpa_authenticator *wpa_auth,
static inline const u8 * wpa_auth_get_psk(struct wpa_authenticator *wpa_auth,
const u8 *addr,
const u8 *p2p_dev_addr,
- const u8 *prev_psk)
+ const u8 *prev_psk, size_t *psk_len)
{
if (wpa_auth->cb->get_psk == NULL)
return NULL;
return wpa_auth->cb->get_psk(wpa_auth->cb_ctx, addr, p2p_dev_addr,
- prev_psk);
+ prev_psk, psk_len);
}
@@ -848,17 +848,16 @@ static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data,
struct wpa_ptk PTK;
int ok = 0;
const u8 *pmk = NULL;
- unsigned int pmk_len;
+ size_t pmk_len;
os_memset(&PTK, 0, sizeof(PTK));
for (;;) {
if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
!wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr,
- sm->p2p_dev_addr, pmk);
+ sm->p2p_dev_addr, pmk, &pmk_len);
if (pmk == NULL)
break;
- pmk_len = PMK_LEN;
} else {
pmk = sm->PMK;
pmk_len = sm->pmk_len;
@@ -2020,11 +2019,14 @@ SM_STATE(WPA_PTK, INITPMK)
SM_STATE(WPA_PTK, INITPSK)
{
const u8 *psk;
+ size_t psk_len;
+
SM_ENTRY_MA(WPA_PTK, INITPSK, wpa_ptk);
- psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr, NULL);
+ psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr, NULL,
+ &psk_len);
if (psk) {
- os_memcpy(sm->PMK, psk, PMK_LEN);
- sm->pmk_len = PMK_LEN;
+ os_memcpy(sm->PMK, psk, psk_len);
+ sm->pmk_len = psk_len;
#ifdef CONFIG_IEEE80211R_AP
os_memcpy(sm->xxkey, psk, PMK_LEN);
sm->xxkey_len = PMK_LEN;
@@ -2619,7 +2621,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
struct wpa_ptk PTK;
int ok = 0, psk_found = 0;
const u8 *pmk = NULL;
- unsigned int pmk_len;
+ size_t pmk_len;
int ft;
const u8 *eapol_key_ie, *key_data, *mic;
u16 key_data_length;
@@ -2642,11 +2644,10 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
!wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr,
- sm->p2p_dev_addr, pmk);
+ sm->p2p_dev_addr, pmk, &pmk_len);
if (pmk == NULL)
break;
psk_found = 1;
- pmk_len = PMK_LEN;
} else {
pmk = sm->PMK;
pmk_len = sm->pmk_len;
@@ -3169,7 +3170,7 @@ SM_STEP(WPA_PTK)
break;
case WPA_PTK_INITPSK:
if (wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr,
- NULL)) {
+ NULL, NULL)) {
SM_ENTER(WPA_PTK, PTKSTART);
#ifdef CONFIG_SAE
} else if (wpa_auth_uses_sae(sm) && sm->pmksa) {
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index 9ef660a..49aadee 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -236,7 +236,7 @@ struct wpa_auth_callbacks {
int value);
int (*get_eapol)(void *ctx, const u8 *addr, wpa_eapol_variable var);
const u8 * (*get_psk)(void *ctx, const u8 *addr, const u8 *p2p_dev_addr,
- const u8 *prev_psk);
+ const u8 *prev_psk, size_t *psk_len);
int (*get_msk)(void *ctx, const u8 *addr, u8 *msk, size_t *len);
int (*set_key)(void *ctx, int vlan_id, enum wpa_alg alg,
const u8 *addr, int idx, u8 *key, size_t key_len);
diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c
index dd99db7..0ca27f8 100644
--- a/src/ap/wpa_auth_ft.c
+++ b/src/ap/wpa_auth_ft.c
@@ -443,7 +443,7 @@ static const u8 * wpa_ft_get_psk(struct wpa_authenticator *wpa_auth,
if (wpa_auth->cb->get_psk == NULL)
return NULL;
return wpa_auth->cb->get_psk(wpa_auth->cb_ctx, addr, p2p_dev_addr,
- prev_psk);
+ prev_psk, NULL);
}
diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
index 5a09fb3..a44fd90 100644
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -238,12 +238,15 @@ static int hostapd_wpa_auth_get_eapol(void *ctx, const u8 *addr,
static const u8 * hostapd_wpa_auth_get_psk(void *ctx, const u8 *addr,
const u8 *p2p_dev_addr,
- const u8 *prev_psk)
+ const u8 *prev_psk, size_t *psk_len)
{
struct hostapd_data *hapd = ctx;
struct sta_info *sta = ap_get_sta(hapd, addr);
const u8 *psk;
+ if (psk_len)
+ *psk_len = PMK_LEN;
+
#ifdef CONFIG_SAE
if (sta && sta->auth_alg == WLAN_AUTH_SAE) {
if (!sta->sae || prev_psk)
@@ -259,8 +262,11 @@ static const u8 * hostapd_wpa_auth_get_psk(void *ctx, const u8 *addr,
#ifdef CONFIG_OWE
if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) &&
- sta && sta->owe_pmk)
+ sta && sta->owe_pmk) {
+ if (psk_len)
+ *psk_len = sta->owe_pmk_len;
return sta->owe_pmk;
+ }
#endif /* CONFIG_OWE */
psk = hostapd_get_psk(hapd->conf, addr, p2p_dev_addr, prev_psk);
diff --git a/wpa_supplicant/ibss_rsn.c b/wpa_supplicant/ibss_rsn.c
index 9b6c416..00919d1 100644
--- a/wpa_supplicant/ibss_rsn.c
+++ b/wpa_supplicant/ibss_rsn.c
@@ -259,9 +259,13 @@ static void auth_logger(void *ctx, const u8 *addr, logger_level level,
static const u8 * auth_get_psk(void *ctx, const u8 *addr,
- const u8 *p2p_dev_addr, const u8 *prev_psk)
+ const u8 *p2p_dev_addr, const u8 *prev_psk,
+ size_t *psk_len)
{
struct ibss_rsn *ibss_rsn = ctx;
+
+ if (psk_len)
+ *psk_len = PMK_LEN;
wpa_printf(MSG_DEBUG, "AUTH: %s (addr=" MACSTR " prev_psk=%p)",
__func__, MAC2STR(addr), prev_psk);
if (prev_psk)
diff --git a/wpa_supplicant/mesh_rsn.c b/wpa_supplicant/mesh_rsn.c
index 628382c..90137c4 100644
--- a/wpa_supplicant/mesh_rsn.c
+++ b/wpa_supplicant/mesh_rsn.c
@@ -75,12 +75,15 @@ static void auth_logger(void *ctx, const u8 *addr, logger_level level,
static const u8 *auth_get_psk(void *ctx, const u8 *addr,
- const u8 *p2p_dev_addr, const u8 *prev_psk)
+ const u8 *p2p_dev_addr, const u8 *prev_psk,
+ size_t *psk_len)
{
struct mesh_rsn *mesh_rsn = ctx;
struct hostapd_data *hapd = mesh_rsn->wpa_s->ifmsh->bss[0];
struct sta_info *sta = ap_get_sta(hapd, addr);
+ if (psk_len)
+ *psk_len = PMK_LEN;
wpa_printf(MSG_DEBUG, "AUTH: %s (addr=" MACSTR " prev_psk=%p)",
__func__, MAC2STR(addr), prev_psk);