]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
OWE: Support DH groups 20 (NIST P-384) and 21 (NIST P-521) in station
authorJouni Malinen <jouni@qca.qualcomm.com>
Sun, 8 Oct 2017 13:39:08 +0000 (16:39 +0300)
committerJouni Malinen <j@w1.fi>
Sun, 8 Oct 2017 14:12:35 +0000 (17:12 +0300)
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>
src/rsn_supp/wpa.c
src/rsn_supp/wpa.h
src/rsn_supp/wpa_i.h
wpa_supplicant/Android.mk
wpa_supplicant/Makefile
wpa_supplicant/config.c
wpa_supplicant/config_file.c
wpa_supplicant/config_ssid.h
wpa_supplicant/sme.c

index 04c755d01a7dba6126de78ac3d41ef10ff7152e7..d29565f9b06d163546688adecdf01f73dfc21ae6 100644 (file)
@@ -16,6 +16,8 @@
 #include "crypto/random.h"
 #include "crypto/aes_siv.h"
 #include "crypto/sha256.h"
+#include "crypto/sha384.h"
+#include "crypto/sha512.h"
 #include "common/ieee802_11_defs.h"
 #include "common/ieee802_11_common.h"
 #include "eap_common/eap_defs.h"
@@ -4168,15 +4170,27 @@ int wpa_fils_is_completed(struct wpa_sm *sm)
 
 #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;
+       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);
-       sm->owe_ecdh = crypto_ecdh_init(OWE_DH_GROUP);
+       sm->owe_ecdh = crypto_ecdh_init(group);
        if (!sm->owe_ecdh)
                goto fail;
+       sm->owe_group = group;
        pub = crypto_ecdh_get_pubkey(sm->owe_ecdh, 0);
+       pub = wpabuf_zeropad(pub, prime_len);
        if (!pub)
                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, 1 + 2 + wpabuf_len(pub));
        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_free(pub);
        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;
        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];
+       size_t hash_len, prime_len;
 
        if (!resp_ies ||
            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);
-       if (group != OWE_DH_GROUP) {
+       if (group != sm->owe_group) {
                wpa_printf(MSG_INFO,
                           "OWE: Unexpected Diffie-Hellman group in response: %u",
                           group);
@@ -4235,9 +4250,19 @@ int owe_process_assoc_resp(struct wpa_sm *sm, const u8 *resp_ies,
                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,
                                         elems.owe_dh + 2,
                                         elems.owe_dh_len - 2);
+       secret = wpabuf_zeropad(secret, prime_len);
        if (!secret) {
                wpa_printf(MSG_DEBUG, "OWE: Invalid peer DH public key");
                return -1;
@@ -4257,8 +4282,21 @@ int owe_process_assoc_resp(struct wpa_sm *sm, const u8 *resp_ies,
        len[0] = wpabuf_len(pub);
        addr[1] = elems.owe_dh + 2;
        len[1] = elems.owe_dh_len - 2;
-       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 {
+               res = -1;
+               hash_len = 0;
+       }
+       pub = wpabuf_zeropad(pub, prime_len);
+       if (res < 0 || !pub) {
                wpabuf_free(pub);
                wpabuf_clear_free(secret);
                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_free(pub);
        wpabuf_put_data(hkey, elems.owe_dh + 2, elems.owe_dh_len - 2); /* A */
-       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, sm->owe_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 -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) */
 
-       res = hmac_sha256_kdf(prk, SHA256_MAC_LEN, NULL, (const u8 *) info,
-                             os_strlen(info), sm->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), 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)
                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);
        /* TODO: Add PMKSA cache entry */
 
index 958489d8ed9737385a0a1737f4aaf3587993bd4f..e7d1b787697627b8b0b6252aec238a01ba0e014f 100644 (file)
@@ -457,7 +457,7 @@ struct wpabuf * fils_build_assoc_req(struct wpa_sm *sm, const u8 **kek,
                                     unsigned int num_hlp);
 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,
                           size_t resp_ies_len);
 
index 82e194188081a71af4aff25b0f6eb1f81883136d..ab8411e8b79735edd8cbf40af266137b2fb7e660 100644 (file)
@@ -161,6 +161,7 @@ struct wpa_sm {
 
 #ifdef CONFIG_OWE
        struct crypto_ecdh *owe_ecdh;
+       u16 owe_group;
 #endif /* CONFIG_OWE */
 };
 
index 9e147e9a0bc4d238dec47a9ff50801c33d874375..b6a9a3333cf6dce179930218ad40ed1b8f82325a 100644 (file)
@@ -263,6 +263,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
index b62b898d6616bccee32b6d659ec76af07568fa39..0ae9eff237f9d6e9fd70e0bb789cc05cc101b3de 100644 (file)
@@ -296,6 +296,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
index bf3defbf7c64cf2c3ba1b510057454630e72b5ee..79f36b945b8c00735901972b87d3198ef1924537 100644 (file)
@@ -2281,6 +2281,7 @@ static const struct parse_data ssid_fields[] = {
        { STR_LEN(dpp_csign) },
        { INT(dpp_csign_expiry) },
 #endif /* CONFIG_DPP */
+       { INT_RANGE(owe_group, 0, 65535) },
 };
 
 #undef OFFSET
index 3b351e8b64d60eecd4a896a4f0c7662c87120739..b2f760ae4892721f698096e6229b9d8226c44f52 100644 (file)
@@ -873,6 +873,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
        STR(dpp_csign);
        INT(dpp_csign_expiry);
 #endif /* CONFIG_DPP */
+       INT(owe_group);
 #ifdef CONFIG_HT_OVERRIDES
        INT_DEF(disable_ht, DEFAULT_DISABLE_HT);
        INT_DEF(disable_ht40, DEFAULT_DISABLE_HT40);
index 737ef42ff4458d0366d63ff6323045f285b65199..120218f486bda691a3d96d4fbb92fc83b9fb4291 100644 (file)
@@ -893,6 +893,17 @@ struct wpa_ssid {
         * 0 indicates no expiration.
         */
        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 */
index a92fb4573c2e86ae466ee0eebcfcc3ac67519731..4023026bc236cae44134de37d2ad3d6cd1bd8c9f 100644 (file)
@@ -1195,8 +1195,11 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode,
        if (auth_type == WLAN_AUTH_OPEN &&
            wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
                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) {
                        wpa_printf(MSG_ERROR,
                                   "OWE: Failed to build IE for Association Request frame");