Ver Fonte

wpa_supplicant: wps code updation

Update WPS code with upstream. Also moved ESP specific code
in another esp code folder.
Kapil Gupta há 4 anos atrás
pai
commit
ecc87cfc8d
38 ficheiros alterados com 2358 adições e 1751 exclusões
  1. 8 9
      components/wpa_supplicant/CMakeLists.txt
  2. 5 13
      components/wpa_supplicant/esp_supplicant/include/esp_wps.h
  3. 0 0
      components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-bignum.c
  4. 0 0
      components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c
  5. 2 13
      components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-rsa.c
  6. 0 0
      components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls.c
  7. 0 0
      components/wpa_supplicant/esp_supplicant/src/crypto/tls_mbedtls.c
  8. 7 74
      components/wpa_supplicant/esp_supplicant/src/esp_wpa2.c
  9. 42 18
      components/wpa_supplicant/esp_supplicant/src/esp_wpas_glue.c
  10. 14 13
      components/wpa_supplicant/esp_supplicant/src/esp_wpas_glue.h
  11. 169 415
      components/wpa_supplicant/esp_supplicant/src/esp_wps.c
  12. 80 0
      components/wpa_supplicant/esp_supplicant/src/esp_wps_i.h
  13. 6 0
      components/wpa_supplicant/src/common/ieee802_11_defs.h
  14. 3 3
      components/wpa_supplicant/src/common/wnm_sta.c
  15. 33 0
      components/wpa_supplicant/src/eap_common/eap_wsc_common.c
  16. 27 0
      components/wpa_supplicant/src/eap_common/eap_wsc_common.h
  17. 1 1
      components/wpa_supplicant/src/rsn_supp/pmksa_cache.c
  18. 5 13
      components/wpa_supplicant/src/rsn_supp/wpa.c
  19. 1 1
      components/wpa_supplicant/src/rsn_supp/wpa.h
  20. 2 0
      components/wpa_supplicant/src/rsn_supp/wpa_i.h
  21. 142 130
      components/wpa_supplicant/src/utils/common.c
  22. 3 3
      components/wpa_supplicant/src/utils/common.h
  23. 3 9
      components/wpa_supplicant/src/utils/wpa_debug.c
  24. 191 35
      components/wpa_supplicant/src/wps/wps.c
  25. 172 129
      components/wpa_supplicant/src/wps/wps.h
  26. 210 98
      components/wpa_supplicant/src/wps/wps_attr_build.c
  27. 131 96
      components/wpa_supplicant/src/wps/wps_attr_parse.c
  28. 24 27
      components/wpa_supplicant/src/wps/wps_attr_parse.h
  29. 43 101
      components/wpa_supplicant/src/wps/wps_attr_process.c
  30. 401 123
      components/wpa_supplicant/src/wps/wps_common.c
  31. 29 25
      components/wpa_supplicant/src/wps/wps_defs.h
  32. 49 46
      components/wpa_supplicant/src/wps/wps_dev_attr.c
  33. 5 3
      components/wpa_supplicant/src/wps/wps_dev_attr.h
  34. 279 138
      components/wpa_supplicant/src/wps/wps_enrollee.c
  35. 28 19
      components/wpa_supplicant/src/wps/wps_i.h
  36. 223 185
      components/wpa_supplicant/src/wps/wps_registrar.c
  37. 20 8
      components/wpa_supplicant/src/wps/wps_validate.c
  38. 0 3
      tools/ci/check_copyright_ignore.txt

+ 8 - 9
components/wpa_supplicant/CMakeLists.txt

@@ -22,6 +22,7 @@ set(srcs "port/os_xtensa.c"
     "src/crypto/sha384-prf.c"
     "src/crypto/md4-internal.c"
     "src/crypto/sha1-tprf.c"
+    "src/eap_common/eap_wsc_common.c"
     "src/eap_peer/chap.c"
     "src/eap_peer/eap.c"
     "src/eap_peer/eap_common.c"
@@ -51,9 +52,8 @@ set(srcs "port/os_xtensa.c"
     "src/wps/wps_attr_process.c"
     "src/wps/wps_common.c"
     "src/wps/wps_dev_attr.c"
-    "src/wps/wps_enrollee.c"
-    "src/wps/wps_registrar.c"
-    "src/wps/wps_validate.c")
+    "src/wps/wps_enrollee.c")
+#    "src/wps/wps_registrar.c")
 
 set(esp_srcs "esp_supplicant/src/esp_wpa2.c"
     "esp_supplicant/src/esp_wpa_main.c"
@@ -66,7 +66,7 @@ if(CONFIG_ESP_WIFI_SOFTAP_SUPPORT)
 endif()
 
 if(CONFIG_WPA_MBEDTLS_CRYPTO)
-    set(tls_src "src/crypto/tls_mbedtls.c")
+    set(tls_src "esp_supplicant/src/crypto/tls_mbedtls.c")
 else()
     set(tls_src
     "src/tls/asn1.c"
@@ -91,9 +91,9 @@ endif()
 
 if(CONFIG_WPA_MBEDTLS_CRYPTO)
     set(crypto_src
-    "src/crypto/crypto_mbedtls.c"
-    "src/crypto/crypto_mbedtls-bignum.c"
-    "src/crypto/crypto_mbedtls-ec.c")
+    "esp_supplicant/src/crypto/crypto_mbedtls.c"
+    "esp_supplicant/src/crypto/crypto_mbedtls-bignum.c"
+    "esp_supplicant/src/crypto/crypto_mbedtls-ec.c")
     # Add internal RC4 if RC4 is disabled in mbedtls
     if(CONFIG_MBEDTLS_RC4_DISABLED)
         set(crypto_src ${crypto_src} "src/crypto/rc4.c")
@@ -133,7 +133,6 @@ else()
     "src/crypto/crypto_internal-cipher.c"
     "src/crypto/crypto_internal-modexp.c"
     "src/crypto/crypto_internal-rsa.c"
-    "src/crypto/crypto_mbedtls-rsa.c"
     "src/crypto/crypto_internal.c"
     "src/crypto/des-internal.c"
     "src/crypto/md4-internal.c"
@@ -180,7 +179,7 @@ endif()
 idf_component_register(SRCS "${srcs}" ${esp_srcs} "${tls_src}" "${roaming_src}"
                             "${crypto_src}" "${mbo_src}" "${dpp_src}"
                     INCLUDE_DIRS include port/include esp_supplicant/include
-                    PRIV_INCLUDE_DIRS src src/utils esp_supplicant/src
+                    PRIV_INCLUDE_DIRS src src/utils esp_supplicant/src src/crypto
                     PRIV_REQUIRES mbedtls esp_timer)
 
 target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-strict-aliasing -Wno-write-strings -Werror)

+ 5 - 13
components/wpa_supplicant/esp_supplicant/include/esp_wps.h

@@ -1,16 +1,8 @@
-// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/*
+ * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
 
 #ifndef __ESP_WPS_H__
 #define __ESP_WPS_H__

+ 0 - 0
components/wpa_supplicant/src/crypto/crypto_mbedtls-bignum.c → components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-bignum.c


+ 0 - 0
components/wpa_supplicant/src/crypto/crypto_mbedtls-ec.c → components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c


+ 2 - 13
components/wpa_supplicant/src/crypto/crypto_mbedtls-rsa.c → components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-rsa.c

@@ -1,18 +1,7 @@
 /*
- * Copyright (C) Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD, Apache 2.0 License.
+ * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
  *
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * SPDX-License-Identifier: Apache-2.0
  */
 
 #ifdef ESP_PLATFORM

+ 0 - 0
components/wpa_supplicant/src/crypto/crypto_mbedtls.c → components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls.c


+ 0 - 0
components/wpa_supplicant/src/crypto/tls_mbedtls.c → components/wpa_supplicant/esp_supplicant/src/crypto/tls_mbedtls.c


+ 7 - 74
components/wpa_supplicant/esp_supplicant/src/esp_wpa2.c

@@ -40,6 +40,7 @@
 #ifdef CONFIG_MBEDTLS_CERTIFICATE_BUNDLE
 #include "esp_crt_bundle.h"
 #endif
+#include "esp_wpas_glue.h"
 
 #define WPA2_VERSION    "v2.0"
 
@@ -297,74 +298,6 @@ int wpa2_post(uint32_t sig, uint32_t par)
 
 #endif /* USE_WPA2_TASK */
 
-static void wpa2_sendto_wrapper(void *buffer, uint16_t len)
-{
-    esp_wifi_internal_tx(WIFI_IF_STA, buffer, len);
-}
-
-static inline int wpa2_sm_ether_send(struct eap_sm *sm, const u8 *dest, u16 proto,
-                                     const u8 *data, size_t data_len)
-{
-    void *buffer = (void *)(data - sizeof(struct l2_ethhdr));
-    struct l2_ethhdr *eth = NULL;
-
-    if (!buffer) {
-        wpa_printf(MSG_ERROR, "wpa2: invalid data");
-        return ESP_FAIL;
-    } else {
-        eth = (struct l2_ethhdr *)buffer;
-        memcpy(eth->h_dest, dest, ETH_ALEN);
-        memcpy(eth->h_source, sm->ownaddr, ETH_ALEN);
-        eth->h_proto = host_to_be16(proto);
-        wpa2_sendto_wrapper(buffer, sizeof(struct l2_ethhdr) + data_len);
-    }
-
-    return ESP_OK;
-}
-
-u8 *wpa2_sm_alloc_eapol(struct eap_sm *sm, u8 type,
-                        const void *data, u16 data_len,
-                        size_t *msg_len, void **data_pos)
-{
-    void *buffer;
-    struct ieee802_1x_hdr *hdr;
-
-    *msg_len = sizeof(struct ieee802_1x_hdr) + data_len;
-    /* XXX: reserve l2_ethhdr is enough */
-    buffer = os_malloc(*msg_len + sizeof(struct l2_ethhdr));
-
-    if (buffer == NULL) {
-        return NULL;
-    }
-
-    hdr = (struct ieee802_1x_hdr *)((char *)buffer + sizeof(struct l2_ethhdr));
-    hdr->version = 0x01;
-    hdr->type = type;
-    hdr->length = host_to_be16(data_len);
-
-    if (data) {
-        memcpy(hdr + 1, data, data_len);
-    } else {
-        memset(hdr + 1, 0, data_len);
-    }
-
-    if (data_pos) {
-        *data_pos = hdr + 1;
-    }
-
-    return (u8 *) hdr;
-}
-
-
-void wpa2_sm_free_eapol(u8 *buffer)
-{
-    if (buffer != NULL) {
-        buffer = buffer - sizeof(struct l2_ethhdr);
-        os_free(buffer);
-    }
-
-}
-
 int eap_sm_send_eapol(struct eap_sm *sm, struct wpabuf *resp)
 {
     size_t outlen;
@@ -379,15 +312,15 @@ int eap_sm_send_eapol(struct eap_sm *sm, struct wpabuf *resp)
         return WPA_ERR_INVALID_BSSID;
     }
 
-    outbuf = wpa2_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAP_PACKET,
+    outbuf = wpa_alloc_eapol(sm, IEEE802_1X_TYPE_EAP_PACKET,
                                  wpabuf_head_u8(resp), wpabuf_len(resp),
                                  &outlen, NULL);
     if (!outbuf) {
         return ESP_ERR_NO_MEM;
     }
 
-    ret = wpa2_sm_ether_send(sm, bssid, ETH_P_EAPOL, outbuf, outlen);
-    wpa2_sm_free_eapol(outbuf);
+    ret = wpa_ether_send(sm, bssid, ETH_P_EAPOL, outbuf, outlen);
+    wpa_free_eapol(outbuf);
     if (ret) {
         return ESP_FAIL;
     }
@@ -718,14 +651,14 @@ static int wpa2_start_eapol_internal(void)
         return WPA_ERR_INVALID_BSSID;
     }
 
-    buf = wpa2_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_START, (u8 *)"", 0, &len, NULL);
+    buf = wpa_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_START, (u8 *)"", 0, &len, NULL);
     if (!buf) {
         return ESP_FAIL;
     }
 
     wpa2_set_eap_state(WPA2_ENT_EAP_STATE_IN_PROGRESS);
-    wpa2_sm_ether_send(sm, bssid, ETH_P_EAPOL, buf, len);
-    wpa2_sm_free_eapol(buf);
+    wpa_ether_send(sm, bssid, ETH_P_EAPOL, buf, len);
+    wpa_free_eapol(buf);
     return ESP_OK;
 }
 

+ 42 - 18
components/wpa_supplicant/esp_supplicant/src/esp_wpas_glue.c

@@ -1,16 +1,8 @@
-// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/*
+ * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
 
 #ifdef ESP_SUPPLICANT
 
@@ -19,10 +11,12 @@
 #include "common/eapol_common.h"
 #include "rsn_supp/wpa.h"
 #include "rsn_supp/pmksa_cache.h"
+#include "esp_wpas_glue.h"
+#include "esp_private/wifi.h"
 
-u8   *wpa_sm_alloc_eapol(struct wpa_sm *sm, u8 type,
-                         const void *data, u16 data_len,
-                         size_t *msg_len, void **data_pos)
+u8 *wpa_alloc_eapol(void *sm, u8 type,
+                    const void *data, u16 data_len,
+                    size_t *msg_len, void **data_pos)
 {
     void *buffer;
     struct ieee802_1x_hdr *hdr;
@@ -38,7 +32,7 @@ u8   *wpa_sm_alloc_eapol(struct wpa_sm *sm, u8 type,
     /* XXX: reserve l2_ethhdr is enough */
     hdr = (struct ieee802_1x_hdr *)((char *)buffer + sizeof(struct l2_ethhdr));
 
-    hdr->version = sm->eapol_version;
+    hdr->version = DEFAULT_EAPOL_VERSION;
     hdr->type = type;
     hdr->length = host_to_be16(data_len);
 
@@ -55,12 +49,42 @@ u8   *wpa_sm_alloc_eapol(struct wpa_sm *sm, u8 type,
     return (u8 *) hdr;
 }
 
-void  wpa_sm_free_eapol(u8 *buffer)
+void wpa_free_eapol(u8 *buffer)
 {
+    if (!buffer) {
+        return;
+    }
     buffer = buffer - sizeof(struct l2_ethhdr);
     os_free(buffer);
 }
 
+int wpa_ether_send(void *ctx, const u8 *dest, u16 proto,
+                   const u8 *data, size_t data_len)
+{
+    void *buffer = (void *)(data - sizeof(struct l2_ethhdr));
+    struct l2_ethhdr *eth = (struct l2_ethhdr *)buffer;
+
+    os_memcpy(eth->h_dest, dest, ETH_ALEN);
+    os_memcpy(eth->h_source, gWpaSm.own_addr, ETH_ALEN);
+    eth->h_proto = host_to_be16(proto);
+
+    esp_wifi_internal_tx(WIFI_IF_STA, buffer, sizeof(struct l2_ethhdr) + data_len);
+
+    return ESP_OK;
+}
+
+u8 *wpa_sm_alloc_eapol(struct wpa_sm *sm, u8 type,
+                       const void *data, u16 data_len,
+                       size_t *msg_len, void **data_pos)
+{
+    return wpa_alloc_eapol(sm, type, data, data_len, msg_len, data_pos);
+}
+
+void wpa_sm_free_eapol(u8 *buffer)
+{
+    return wpa_free_eapol(buffer);
+}
+
 void  wpa_sm_deauthenticate(struct wpa_sm *sm, u8 reason_code)
 {
 

+ 14 - 13
components/wpa_supplicant/esp_supplicant/src/esp_wpas_glue.h

@@ -1,16 +1,8 @@
-// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/*
+ * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
 
 #ifndef WPAS_GLUE_H
 #define WPAS_GLUE_H
@@ -30,4 +22,13 @@ int wpa_sm_get_beacon_ie(struct wpa_sm *sm);
 
 void wpa_sm_free_eapol(u8 *buffer);
 
+u8 *wpa_alloc_eapol(void *sm, u8 type,
+                    const void *data, u16 data_len,
+                    size_t *msg_len, void **data_pos);
+
+void wpa_free_eapol(u8 *buffer);
+
+int wpa_ether_send(void *ctx, const u8 *dest, u16 proto,
+                   const u8 *data, size_t data_len);
+
 #endif /* WPAS_GLUE_H */

Diff do ficheiro suprimidas por serem muito extensas
+ 169 - 415
components/wpa_supplicant/esp_supplicant/src/esp_wps.c


+ 80 - 0
components/wpa_supplicant/esp_supplicant/src/esp_wps_i.h

@@ -0,0 +1,80 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* WPS message flag */
+enum wps_msg_flag {
+    WPS_MSG_FLAG_MORE = 0x01,
+    WPS_MSG_FLAG_LEN = 0x02
+};
+
+#ifdef USE_WPS_TASK
+enum wps_sig_type {
+    SIG_WPS_ENABLE = 1,         //1
+    SIG_WPS_DISABLE,            //2
+    SIG_WPS_START,              //3
+    SIG_WPS_RX,                 //4
+    SIG_WPS_TIMER_TIMEOUT,      //5
+    SIG_WPS_TIMER_MSG_TIMEOUT,  //6
+    SIG_WPS_TIMER_SUCCESS_CB,   //7
+    SIG_WPS_TIMER_SCAN,         //8
+    SIG_WPS_TIMER_EAPOL_START,  //9
+    SIG_WPS_NUM,                //10
+};
+#endif
+
+#define WPS_IGNORE_SEL_REG_MAX_CNT	4
+
+#define WPS_MAX_DIS_AP_NUM	10
+
+/* Bssid of the discard AP which is discarded for not select reg or other reason */
+struct discard_ap_list_t{
+	u8 bssid[6];
+};
+
+#ifndef MAX_PASSPHRASE_LEN
+#define MAX_PASSPHRASE_LEN 64
+#endif
+
+#define WPS_OUTBUF_SIZE 500
+struct wps_sm {
+    struct wps_config *wps_cfg;
+    struct wps_context *wps_ctx;
+    struct wps_data *wps;
+    char identity[32];
+    u8 identity_len;
+    u8 ownaddr[ETH_ALEN];
+    u8 bssid[ETH_ALEN];
+    u8 ssid[MAX_CRED_COUNT][SSID_MAX_LEN];
+    u8 ssid_len[MAX_CRED_COUNT];
+    char key[MAX_CRED_COUNT][MAX_PASSPHRASE_LEN];
+    u8 key_len[MAX_CRED_COUNT];
+    u8 ap_cred_cnt;
+    struct wps_device_data *dev;
+    u8 uuid[16];
+    ETSTimer wps_timeout_timer;
+    ETSTimer wps_msg_timeout_timer;
+    ETSTimer wps_scan_timer;
+    ETSTimer wps_success_cb_timer;
+    ETSTimer wps_eapol_start_timer;
+    u8 current_identifier;
+    bool is_wps_scan;
+    u8 channel;
+    u8 scan_cnt;
+#ifdef USE_WPS_TASK
+    u8 wps_sig_cnt[SIG_WPS_NUM];
+#endif
+    u8 discover_ssid_cnt;
+    bool ignore_sel_reg;
+    struct discard_ap_list_t dis_ap_list[WPS_MAX_DIS_AP_NUM];
+    u8 discard_ap_cnt;
+};
+
+struct wps_sm *wps_sm_get(void);
+int wps_station_wps_unregister_cb(void);
+int wps_start_pending(void);
+int wps_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len);
+
+int wps_dev_deinit(struct wps_device_data *dev);

+ 6 - 0
components/wpa_supplicant/src/common/ieee802_11_defs.h

@@ -515,6 +515,12 @@ struct ieee80211_ht_operation {
 #define HT_OPER_PARAM_PCO_PHASE				((u16) BIT(11))
 /* B36..B39 - Reserved */
 
+#define MULTI_AP_SUB_ELEM_TYPE 0x06
+#define MULTI_AP_TEAR_DOWN BIT(4)
+#define MULTI_AP_FRONTHAUL_BSS BIT(5)
+#define MULTI_AP_BACKHAUL_BSS BIT(6)
+#define MULTI_AP_BACKHAUL_STA BIT(7)
+
 #define WMM_OUI_TYPE 2
 #define WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0
 #define WMM_OUI_SUBTYPE_PARAMETER_ELEMENT 1

+ 3 - 3
components/wpa_supplicant/src/common/wnm_sta.c

@@ -354,7 +354,7 @@ compare_scan_neighbor_results(struct wpa_supplicant *wpa_s, os_time_t age_secs,
 			struct os_reltime now;
 
 			if (os_get_reltime(&now) == 0 &&
-			    os_time_expired(&now, &target->last_update,
+			    os_reltime_expired(&now, &target->last_update,
 					       age_secs)) {
 				wpa_printf(MSG_DEBUG,
 					   "Candidate BSS is more than %jd seconds old",
@@ -546,7 +546,7 @@ static void wnm_add_cand_list(struct wpa_supplicant *wpa_s, struct wpabuf **buf)
 	 * list.
 	 */
 	os_get_reltime(&now);
-	if (os_time_expired(&now, &wpa_s->last_scan, 10))
+	if (os_reltime_expired(&now, &wpa_s->last_scan, 10))
 		return;
 
 	wpa_printf(MSG_DEBUG,
@@ -1010,7 +1010,7 @@ static void ieee802_11_rx_bss_trans_mgmt_req(struct wpa_supplicant *wpa_s,
 			struct os_reltime now;
 
 			os_get_reltime(&now);
-			if (!os_time_expired(&now, &wpa_s->last_scan, 10)) {
+			if (!os_reltime_expired(&now, &wpa_s->last_scan, 10)) {
 				wpa_printf(MSG_DEBUG,
 					   "WNM: Try to use recent scan results");
 				if (wnm_scan_process(wpa_s, 0) > 0)

+ 33 - 0
components/wpa_supplicant/src/eap_common/eap_wsc_common.c

@@ -0,0 +1,33 @@
+/*
+ * EAP-WSC common routines for Wi-Fi Protected Setup
+ * Copyright (c) 2007, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "eap_peer/eap_defs.h"
+#include "eap_peer/eap_common.h"
+#include "wps/wps.h"
+#include "eap_wsc_common.h"
+
+struct wpabuf * eap_wsc_build_frag_ack(u8 id, u8 code)
+{
+	struct wpabuf *msg;
+
+	msg = eap_msg_alloc(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, 2, code, id);
+	if (msg == NULL) {
+		wpa_printf(MSG_ERROR, "EAP-WSC: Failed to allocate memory for "
+			   "FRAG_ACK");
+		return NULL;
+	}
+
+	wpa_printf(MSG_DEBUG, "EAP-WSC: Send WSC/FRAG_ACK");
+	wpabuf_put_u8(msg, WSC_FRAG_ACK); /* Op-Code */
+	wpabuf_put_u8(msg, 0); /* Flags */
+
+	return msg;
+}

+ 27 - 0
components/wpa_supplicant/src/eap_common/eap_wsc_common.h

@@ -0,0 +1,27 @@
+/*
+ * EAP-WSC definitions for Wi-Fi Protected Setup
+ * Copyright (c) 2007, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef EAP_WSC_COMMON_H
+#define EAP_WSC_COMMON_H
+
+#define EAP_VENDOR_TYPE_WSC 1
+
+#define WSC_FLAGS_MF 0x01
+#define WSC_FLAGS_LF 0x02
+
+#define WSC_ID_REGISTRAR "WFA-SimpleConfig-Registrar-1-0"
+#define WSC_ID_REGISTRAR_LEN 30
+#define WSC_ID_ENROLLEE "WFA-SimpleConfig-Enrollee-1-0"
+#define WSC_ID_ENROLLEE_LEN 29
+
+#define WSC_FRAGMENT_SIZE 1400
+
+
+struct wpabuf * eap_wsc_build_frag_ack(u8 id, u8 code);
+
+#endif /* EAP_WSC_COMMON_H */

+ 1 - 1
components/wpa_supplicant/src/rsn_supp/pmksa_cache.c

@@ -38,7 +38,7 @@ static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa);
 
 static void _pmksa_cache_free_entry(struct rsn_pmksa_cache_entry *entry)
 {
-    wpa_bin_clear_free(entry, sizeof(*entry));
+    bin_clear_free(entry, sizeof(*entry));
 }
 
 

+ 5 - 13
components/wpa_supplicant/src/rsn_supp/wpa.c

@@ -191,7 +191,7 @@ static inline int   wpa_sm_get_bssid(struct wpa_sm *sm, u8 *bssid)
 }
 
  /*
- * wpa_ether_send - Send Ethernet frame
+ * wpa_sm_ether_send - Send Ethernet frame
  * @wpa_s: Pointer to wpa_supplicant data
  * @dest: Destination MAC address
  * @proto: Ethertype in host byte order
@@ -199,18 +199,10 @@ static inline int   wpa_sm_get_bssid(struct wpa_sm *sm, u8 *bssid)
  * @len: Frame payload length
  * Returns: >=0 on success, <0 on failure
  */
-static inline int wpa_sm_ether_send( struct wpa_sm *sm, const u8 *dest, u16 proto,
-        const u8 *data, size_t data_len)
+static inline int wpa_sm_ether_send(struct wpa_sm *sm, const u8 *dest, u16 proto,
+                                    const u8 *data, size_t data_len)
 {
-    void *buffer = (void *)(data - sizeof(struct l2_ethhdr));
-    struct l2_ethhdr *eth = (struct l2_ethhdr *)buffer;
-
-    memcpy(eth->h_dest, dest, ETH_ALEN);
-    memcpy(eth->h_source, sm->own_addr, ETH_ALEN);
-    eth->h_proto = host_to_be16(proto);
-    sm->sendto(buffer, sizeof(struct l2_ethhdr) + data_len);
-
-    return 0;
+    return wpa_ether_send(sm, dest, proto, data, data_len);
 }
 
 /**
@@ -2176,7 +2168,7 @@ bool wpa_sm_init(char * payload, WPA_SEND_FUNC snd_func,
     struct wpa_sm *sm = &gWpaSm;
     u16 spp_attrubute = 0;
 
-    sm->eapol_version = 0x1;   /* DEFAULT_EAPOL_VERSION */
+    sm->eapol_version = DEFAULT_EAPOL_VERSION;   /* DEFAULT_EAPOL_VERSION */
     sm->sendto = snd_func;
     sm->config_assoc_ie = set_assoc_ie_func;
     sm->install_ppkey = ppinstallkey;

+ 1 - 1
components/wpa_supplicant/src/rsn_supp/wpa.h

@@ -19,10 +19,10 @@
 #include "wpa_i.h"
 
 struct wpa_sm;
+extern struct wpa_sm gWpaSm;
 
 #define WPA_SM_STATE(_sm) ((_sm)->wpa_state)
 
-
 bool wpa_sta_is_cur_pmksa_set(void);
 bool wpa_sta_in_4way_handshake(void);
 bool wpa_sta_cur_pmksa_matches_akm(void);

+ 2 - 0
components/wpa_supplicant/src/rsn_supp/wpa_i.h

@@ -10,6 +10,8 @@
 #define WPA_I_H
 
 extern struct wpa_sm gWpaSm;
+#define DEFAULT_EAPOL_VERSION 1
+
 struct install_key {
     int keys_cleared;
     enum wpa_alg alg;

+ 142 - 130
components/wpa_supplicant/src/utils/common.c

@@ -1,35 +1,18 @@
 /*
  * wpa_supplicant/hostapd / common helper functions, etc.
- * Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
  */
 
-#include "utils/includes.h"
+#include "includes.h"
+#include <limits.h>
 
-#include "utils/common.h"
 #include <time.h>
+#include "common/ieee802_11_defs.h"
+#include "common.h"
 
-/**
- * inc_byte_array - Increment arbitrary length byte array by one
- * @counter: Pointer to byte array
- * @len: Length of the counter in bytes
- *
- * This function increments the last byte of the counter by one and continues
- * rolling over to more significant bytes if the byte was incremented from
- * 0xff to 0x00.
- */
-void inc_byte_array(u8 *counter, size_t len)
-{
-	int pos = len - 1;
-	while (pos >= 0) {
-		counter[pos]++;
-		if (counter[pos] != 0)
-			break;
-		pos--;
-	}
-}
 
 static int hex2num(char c)
 {
@@ -56,6 +39,36 @@ int hex2byte(const char *hex)
 }
 
 
+/**
+ * hwaddr_aton2 - Convert ASCII string to MAC address (in any known format)
+ * @txt: MAC address as a string (e.g., 00:11:22:33:44:55 or 0011.2233.4455)
+ * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
+ * Returns: Characters used (> 0) on success, -1 on failure
+ */
+int hwaddr_aton2(const char *txt, u8 *addr)
+{
+	int i;
+	const char *pos = txt;
+
+	for (i = 0; i < 6; i++) {
+		int a, b;
+
+		while (*pos == ':' || *pos == '.' || *pos == '-')
+			pos++;
+
+		a = hex2num(*pos++);
+		if (a < 0)
+			return -1;
+		b = hex2num(*pos++);
+		if (b < 0)
+			return -1;
+		*addr++ = (a << 4) | b;
+	}
+
+	return pos - txt;
+}
+
+
 /**
  * hexstr2bin - Convert ASCII hex string into binary data
  * @hex: ASCII hex string (e.g., "01ab")
@@ -81,6 +94,28 @@ int hexstr2bin(const char *hex, u8 *buf, size_t len)
 	return 0;
 }
 
+
+/**
+ * inc_byte_array - Increment arbitrary length byte array by one
+ * @counter: Pointer to byte array
+ * @len: Length of the counter in bytes
+ *
+ * This function increments the last byte of the counter by one and continues
+ * rolling over to more significant bytes if the byte was incremented from
+ * 0xff to 0x00.
+ */
+void inc_byte_array(u8 *counter, size_t len)
+{
+	int pos = len - 1;
+	while (pos >= 0) {
+		counter[pos]++;
+		if (counter[pos] != 0)
+			break;
+		pos--;
+	}
+}
+
+
 void wpa_get_ntp_timestamp(u8 *buf)
 {
 	struct os_time now;
@@ -133,7 +168,7 @@ void printf_encode(char *txt, size_t maxlen, const u8 *data, size_t len)
 			*txt++ = 't';
 			break;
 		default:
-			if (data[i] >= 32 && data[i] <= 127) {
+			if (data[i] >= 32 && data[i] <= 126) {
 				*txt++ = data[i];
 			} else {
 				txt += os_snprintf(txt, end - txt, "\\x%02x",
@@ -229,6 +264,39 @@ size_t printf_decode(u8 *buf, size_t maxlen, const char *str)
 }
 
 
+/**
+ * wpa_ssid_txt - Convert SSID to a printable string
+ * @ssid: SSID (32-octet string)
+ * @ssid_len: Length of ssid in octets
+ * Returns: Pointer to a printable string
+ *
+ * This function can be used to convert SSIDs into printable form. In most
+ * cases, SSIDs do not use unprintable characters, but IEEE 802.11 standard
+ * does not limit the used character set, so anything could be used in an SSID.
+ *
+ * This function uses a static buffer, so only one call can be used at the
+ * time, i.e., this is not re-entrant and the returned buffer must be used
+ * before calling this again.
+ */
+const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len)
+{
+	static char ssid_txt[SSID_MAX_LEN * 4 + 1];
+
+	if (ssid == NULL) {
+		ssid_txt[0] = '\0';
+		return ssid_txt;
+	}
+
+	printf_encode(ssid_txt, sizeof(ssid_txt), ssid, ssid_len);
+	return ssid_txt;
+}
+
+
+void * __hide_aliasing_typecast(void *foo)
+{
+	return foo;
+}
+
 
 char * wpa_config_parse_string(const char *value, size_t *len)
 {
@@ -312,6 +380,19 @@ int wpa_is_hex(const u8 *data, size_t len)
 }
 
 
+int has_ctrl_char(const u8 *data, size_t len)
+{
+	size_t i;
+
+	for (i = 0; i < len; i++) {
+		if (data[i] < 32 || data[i] == 127)
+			return 1;
+	}
+	return 0;
+}
+
+
+
 size_t wpa_merge_byte_arrays(u8 *res, size_t res_len,
 			 const u8 *src1, size_t src1_len,
 			 const u8 *src2, size_t src2_len)
@@ -358,39 +439,36 @@ char * dup_binstr(const void *src, size_t len)
 
 	return res;
 }
-void wpa_bin_clear_free(void *bin, size_t len)
-{
-	if (bin) {
-		os_memset(bin, 0, len);
-		os_free(bin);
-	}
-}
 
-int int_array_len(const int *a)
+
+size_t int_array_len(const int *a)
 {
-	int i;
+	size_t i;
+
 	for (i = 0; a && a[i]; i++)
 		;
 	return i;
 }
 
-void bin_clear_free(void *bin, size_t len)
-{
-	if (bin) {
-		os_memset(bin, 0, len);
-		os_free(bin);
-	}
-}
-
 void str_clear_free(char *str)
 {
 	if (str) {
 		size_t len = os_strlen(str);
-		os_memset(str, 0, len);
+		forced_memzero(str, len);
 		os_free(str);
 	}
 }
 
+
+void bin_clear_free(void *bin, size_t len)
+{
+	if (bin) {
+		forced_memzero(bin, len);
+		os_free(bin);
+	}
+}
+
+
 int os_gmtime(os_time_t t, struct os_tm *tm)
 {
 	struct tm *tm2;
@@ -430,30 +508,6 @@ int os_mktime(int year, int month, int day, int hour, int min, int sec,
 	return 0;
 }
 
-char * get_param(const char *cmd, const char *param)
-{
-	const char *pos, *end;
-	char *val;
-	size_t len;
-
-	pos = os_strstr(cmd, param);
-	if (!pos)
-		return NULL;
-
-	pos += os_strlen(param);
-	end = os_strchr(pos, ' ');
-	if (end)
-		len = end - pos;
-	else
-		len = os_strlen(pos);
-	val = os_malloc(len + 1);
-	if (!val)
-		return NULL;
-	os_memcpy(val, pos, len);
-	val[len] = '\0';
-	return val;
-}
-
 void * os_memdup(const void *src, size_t len)
 {
 	void *r = os_malloc(len);
@@ -463,38 +517,9 @@ void * os_memdup(const void *src, size_t len)
 	return r;
 }
 
-/**
- * hwaddr_aton2 - Convert ASCII string to MAC address (in any known format)
- * @txt: MAC address as a string (e.g., 00:11:22:33:44:55 or 0011.2233.4455)
- * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
- * Returns: Characters used (> 0) on success, -1 on failure
- */
-int hwaddr_aton2(const char *txt, u8 *addr)
-{
-	int i;
-	const char *pos = txt;
-
-	for (i = 0; i < 6; i++) {
-		int a, b;
-
-		while (*pos == ':' || *pos == '.' || *pos == '-')
-			pos++;
-
-		a = hex2num(*pos++);
-		if (a < 0)
-			return -1;
-		b = hex2num(*pos++);
-		if (b < 0)
-			return -1;
-		*addr++ = (a << 4) | b;
-	}
-
-	return pos - txt;
-}
-
-static inline int os_reltime_expired(struct os_time *now,
-				     struct os_time *ts,
-				     os_time_t timeout_secs)
+int os_reltime_expired(struct os_time *now,
+			struct os_time *ts,
+			os_time_t timeout_secs)
 {
 	struct os_time age;
 
@@ -503,12 +528,6 @@ static inline int os_reltime_expired(struct os_time *now,
 		(age.sec == timeout_secs && age.usec > 0);
 }
 
-int os_time_expired(struct os_time *now,
-		struct os_time *ts,
-		os_time_t timeout_secs)
-{
-	return os_reltime_expired(now, ts, timeout_secs);
-}
 
 u8 rssi_to_rcpi(int rssi)
 {
@@ -521,34 +540,27 @@ u8 rssi_to_rcpi(int rssi)
 	return (rssi + 110) * 2;
 }
 
-/**
- * wpa_ssid_txt - Convert SSID to a printable string
- * @ssid: SSID (32-octet string)
- * @ssid_len: Length of ssid in octets
- * Returns: Pointer to a printable string
- *
- * This function can be used to convert SSIDs into printable form. In most
- * cases, SSIDs do not use unprintable characters, but IEEE 802.11 standard
- * does not limit the used character set, so anything could be used in an SSID.
- *
- * This function uses a static buffer, so only one call can be used at the
- * time, i.e., this is not re-entrant and the returned buffer must be used
- * before calling this again.
- */
-const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len)
-{
-	static char ssid_txt[SSID_MAX_LEN * 4 + 1];
 
-	if (ssid == NULL) {
-		ssid_txt[0] = '\0';
-		return ssid_txt;
-	}
+char * get_param(const char *cmd, const char *param)
+{
+	const char *pos, *end;
+	char *val;
+	size_t len;
 
-	printf_encode(ssid_txt, sizeof(ssid_txt), ssid, ssid_len);
-	return ssid_txt;
-}
+	pos = os_strstr(cmd, param);
+	if (!pos)
+		return NULL;
 
-void * __hide_aliasing_typecast(void *foo)
-{
-	return foo;
+	pos += os_strlen(param);
+	end = os_strchr(pos, ' ');
+	if (end)
+		len = end - pos;
+	else
+		len = os_strlen(pos);
+	val = os_malloc(len + 1);
+	if (!val)
+		return NULL;
+	os_memcpy(val, pos, len);
+	val[len] = '\0';
+	return val;
 }

+ 3 - 3
components/wpa_supplicant/src/utils/common.h

@@ -389,7 +389,7 @@ int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data,
 
 int hwaddr_mask_txt(char *buf, size_t len, const u8 *addr, const u8 *mask);
 u8 rssi_to_rcpi(int rssi);
-int os_time_expired(struct os_time *now,
+int os_reltime_expired(struct os_time *now,
 		struct os_time *ts,
 		os_time_t timeout_secs);
 
@@ -408,6 +408,7 @@ const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len);
 
 char * wpa_config_parse_string(const char *value, size_t *len);
 int wpa_is_hex(const u8 *data, size_t len);
+int has_ctrl_char(const u8 *data, size_t len);
 size_t wpa_merge_byte_arrays(u8 *res, size_t res_len,
 			 const u8 *src1, size_t src1_len,
 			 const u8 *src2, size_t src2_len);
@@ -447,8 +448,7 @@ struct wpa_freq_range_list {
 #define TEST_FAIL() 0
 #endif
 
-void wpa_bin_clear_free(void *bin, size_t len);
-int int_array_len(const int *a);
+size_t int_array_len(const int *a);
 void bin_clear_free(void *bin, size_t len);
 void str_clear_free(char *str);
 char * get_param(const char *cmd, const char *param);

+ 3 - 9
components/wpa_supplicant/src/utils/wpa_debug.c

@@ -1,15 +1,9 @@
 /*
  * wpa_supplicant/hostapd / Debug prints
- * Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
  */
 #ifdef ESP_SUPPLICANT
 #include "utils/includes.h"

+ 191 - 35
components/wpa_supplicant/src/wps/wps.c

@@ -5,20 +5,191 @@
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
  */
-#include <string.h>
 
-#include "utils/includes.h"
-#include "rsn_supp/wpa.h"
-#include "utils/common.h"
-#include "common/eapol_common.h"
-#include "utils/wpa_debug.h"
+#include "includes.h"
+
+#include "common.h"
+#include "crypto/dh_group5.h"
 #include "common/ieee802_11_defs.h"
+#include "wps_i.h"
+#include "wps_dev_attr.h"
+
+
+#ifdef CONFIG_WPS_TESTING
+int wps_version_number = 0x20;
+int wps_testing_stub_cred = 0;
+int wps_corrupt_pkhash = 0;
+int wps_force_auth_types_in_use = 0;
+u16 wps_force_auth_types = 0;
+int wps_force_encr_types_in_use = 0;
+u16 wps_force_encr_types = 0;
+#endif /* CONFIG_WPS_TESTING */
+
+
+/**
+ * wps_init - Initialize WPS Registration protocol data
+ * @cfg: WPS configuration
+ * Returns: Pointer to allocated data or %NULL on failure
+ *
+ * This function is used to initialize WPS data for a registration protocol
+ * instance (i.e., each run of registration protocol as a Registrar of
+ * Enrollee. The caller is responsible for freeing this data after the
+ * registration run has been completed by calling wps_deinit().
+ */
+struct wps_data * wps_init(const struct wps_config *cfg)
+{
+	struct wps_data *data = os_zalloc(sizeof(*data));
+	if (data == NULL)
+		return NULL;
+	data->wps = cfg->wps;
+	data->registrar = cfg->registrar;
+	if (cfg->registrar) {
+		os_memcpy(data->uuid_r, cfg->wps->uuid, WPS_UUID_LEN);
+	} else {
+		os_memcpy(data->mac_addr_e, cfg->wps->dev.mac_addr, ETH_ALEN);
+		os_memcpy(data->uuid_e, cfg->wps->uuid, WPS_UUID_LEN);
+	}
+	if (cfg->pin) {
+		data->dev_pw_id = cfg->dev_pw_id;
+		data->dev_password = os_memdup(cfg->pin, cfg->pin_len);
+		if (data->dev_password == NULL) {
+			os_free(data);
+			return NULL;
+		}
+		data->dev_password_len = cfg->pin_len;
+		wpa_hexdump_key(MSG_DEBUG, "WPS: AP PIN dev_password",
+				data->dev_password, data->dev_password_len);
+	}
+
+#ifdef CONFIG_WPS_NFC
+	if (cfg->pin == NULL &&
+	    cfg->dev_pw_id == DEV_PW_NFC_CONNECTION_HANDOVER)
+		data->dev_pw_id = cfg->dev_pw_id;
+
+	if (cfg->wps->ap && !cfg->registrar && cfg->wps->ap_nfc_dev_pw_id) {
+		/* Keep AP PIN as alternative Device Password */
+		data->alt_dev_pw_id = data->dev_pw_id;
+		data->alt_dev_password = data->dev_password;
+		data->alt_dev_password_len = data->dev_password_len;
+
+		data->dev_pw_id = cfg->wps->ap_nfc_dev_pw_id;
+		data->dev_password =
+			os_memdup(wpabuf_head(cfg->wps->ap_nfc_dev_pw),
+				  wpabuf_len(cfg->wps->ap_nfc_dev_pw));
+		if (data->dev_password == NULL) {
+			os_free(data);
+			return NULL;
+		}
+		data->dev_password_len = wpabuf_len(cfg->wps->ap_nfc_dev_pw);
+		wpa_hexdump_key(MSG_DEBUG, "WPS: NFC dev_password",
+			    data->dev_password, data->dev_password_len);
+	}
+#endif /* CONFIG_WPS_NFC */
+
+	data->pbc = cfg->pbc;
+	if (cfg->pbc) {
+		/* Use special PIN '00000000' for PBC */
+		data->dev_pw_id = DEV_PW_PUSHBUTTON;
+		bin_clear_free(data->dev_password, data->dev_password_len);
+		data->dev_password = (u8 *) os_strdup("00000000");
+		if (data->dev_password == NULL) {
+			os_free(data);
+			return NULL;
+		}
+		data->dev_password_len = 8;
+	}
+
+	data->state = data->registrar ? RECV_M1 : SEND_M1;
+
+#ifndef ESP_SUPPLICANT
+	if (cfg->assoc_wps_ie) {
+		struct wps_parse_attr attr;
+		wpa_hexdump_buf(MSG_DEBUG, "WPS: WPS IE from (Re)AssocReq",
+				cfg->assoc_wps_ie);
+		if (wps_parse_msg(cfg->assoc_wps_ie, &attr) < 0) {
+			wpa_printf(MSG_DEBUG, "WPS: Failed to parse WPS IE "
+				   "from (Re)AssocReq");
+		} else if (attr.request_type == NULL) {
+			wpa_printf(MSG_DEBUG, "WPS: No Request Type attribute "
+				   "in (Re)AssocReq WPS IE");
+		} else {
+			wpa_printf(MSG_DEBUG, "WPS: Request Type (from WPS IE "
+				   "in (Re)AssocReq WPS IE): %d",
+				   *attr.request_type);
+			data->request_type = *attr.request_type;
+		}
+	}
+
+	if (cfg->new_ap_settings) {
+		data->new_ap_settings =
+			os_memdup(cfg->new_ap_settings,
+				  sizeof(*data->new_ap_settings));
+		if (data->new_ap_settings == NULL) {
+			bin_clear_free(data->dev_password,
+				       data->dev_password_len);
+			os_free(data);
+			return NULL;
+		}
+	}
+
+	if (cfg->peer_addr)
+		os_memcpy(data->peer_dev.mac_addr, cfg->peer_addr, ETH_ALEN);
+	if (cfg->p2p_dev_addr)
+		os_memcpy(data->p2p_dev_addr, cfg->p2p_dev_addr, ETH_ALEN);
+
+	data->use_psk_key = cfg->use_psk_key;
+	data->pbc_in_m1 = cfg->pbc_in_m1;
+
+	if (cfg->peer_pubkey_hash) {
+		os_memcpy(data->peer_pubkey_hash, cfg->peer_pubkey_hash,
+			  WPS_OOB_PUBKEY_HASH_LEN);
+		data->peer_pubkey_hash_set = 1;
+	}
+
+	data->multi_ap_backhaul_sta = cfg->multi_ap_backhaul_sta;
 
-#include "wps/wps_i.h"
-#include "wps/wps_dev_attr.h"
+#endif
+	return data;
+}
+
+
+/**
+ * wps_deinit - Deinitialize WPS Registration protocol data
+ * @data: WPS Registration protocol data from wps_init()
+ */
+void wps_deinit(struct wps_data *data)
+{
+#ifdef CONFIG_WPS_NFC
+	if (data->registrar && data->nfc_pw_token)
+		wps_registrar_remove_nfc_pw_token(data->wps->registrar,
+						  data->nfc_pw_token);
+#endif /* CONFIG_WPS_NFC */
+
+#ifdef CONFIG_WPS_REGISTRAR
+	if (data->wps_pin_revealed) {
+		wpa_printf(MSG_DEBUG, "WPS: Full PIN information revealed and "
+			   "negotiation failed");
+		if (data->registrar)
+			wps_registrar_invalidate_pin(data->wps->registrar,
+						     data->uuid_e);
+	} else if (data->registrar)
+		wps_registrar_unlock_pin(data->wps->registrar, data->uuid_e);
+#endif
 
-#include "eap_peer/eap_defs.h"
-#include "eap_peer/eap_common.h"
+	wpabuf_clear_free(data->dh_privkey);
+	wpabuf_free(data->dh_pubkey_e);
+	wpabuf_free(data->dh_pubkey_r);
+	wpabuf_free(data->last_msg);
+	bin_clear_free(data->dev_password, data->dev_password_len);
+#ifndef ESP_SUPPLICANT
+	bin_clear_free(data->alt_dev_password, data->alt_dev_password_len);
+	bin_clear_free(data->new_psk, data->new_psk_len);
+#endif /* ESP_SUPPLICANT */
+	wps_device_data_free(&data->peer_dev);
+	bin_clear_free(data->new_ap_settings, sizeof(*data->new_ap_settings));
+	dh5_free(data->dh_ctx);
+	os_free(data);
+}
 
 
 /**
@@ -69,7 +240,7 @@ struct wpabuf * wps_get_msg(struct wps_data *wps, enum wsc_op_code *op_code)
  */
 int wps_is_selected_pbc_registrar(const struct wpabuf *msg)
 {
-    struct wps_parse_attr *attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr));
+    struct wps_parse_attr *attr = os_zalloc(sizeof(struct wps_parse_attr));
 
     if (!attr)
         return 0;
@@ -103,7 +274,6 @@ int wps_is_selected_pbc_registrar(const struct wpabuf *msg)
     return 1;
 }
 
-#ifdef CONFIG_WPS_PIN
 
 static int is_selected_pin_registrar(struct wps_parse_attr *attr)
 {
@@ -143,7 +313,7 @@ int wps_is_selected_pin_registrar(const struct wpabuf *msg)
     struct wps_parse_attr *attr;
     int ret;
 
-    attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr));
+    attr = os_zalloc(sizeof(struct wps_parse_attr));
     if (attr == NULL)
         return -99;
 
@@ -157,7 +327,6 @@ int wps_is_selected_pin_registrar(const struct wpabuf *msg)
 
     return ret;
 }
-#endif
 
 /**
  * wps_is_addr_authorized - Check whether WPS IE authorizes MAC address
@@ -176,7 +345,7 @@ int wps_is_addr_authorized(const struct wpabuf *msg, const u8 *addr,
     const u8 *pos;
     const u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 
-    attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr));
+    attr = os_zalloc(sizeof(struct wps_parse_attr));
     if (attr == NULL) {
         ret = 0;
         goto _out;
@@ -192,11 +361,9 @@ int wps_is_addr_authorized(const struct wpabuf *msg, const u8 *addr,
          * Version 1.0 AP - AuthorizedMACs not used, so revert back to
          * old mechanism of using SelectedRegistrar.
          */
-#ifdef CONFIG_WPS_PIN
 
         ret = is_selected_pin_registrar(attr);
         goto _out;
-#endif
     }
 
     if (!attr->authorized_macs) {
@@ -343,7 +510,7 @@ struct wpabuf * wps_build_assoc_req_ie(enum wps_request_type req_type)
 
     if (wps_build_version(ie) ||
         wps_build_req_type(ie, req_type) ||
-        wps_build_wfa_ext(ie, 0, NULL, 0)) {
+        wps_build_wfa_ext(ie, 0, NULL, 0, 0)) {
         wpabuf_free(ie);
         return NULL;
     }
@@ -377,7 +544,7 @@ struct wpabuf * wps_build_assoc_resp_ie(void)
 
     if (wps_build_version(ie) ||
         wps_build_resp_type(ie, WPS_RESP_AP) ||
-        wps_build_wfa_ext(ie, 0, NULL, 0)) {
+        wps_build_wfa_ext(ie, 0, NULL, 0, 0)) {
         wpabuf_free(ie);
         return NULL;
     }
@@ -410,30 +577,26 @@ struct wpabuf * wps_build_probe_req_ie(u16 pw_id, struct wps_device_data *dev,
 {
     struct wpabuf *ie;
 
-    wpa_printf(MSG_DEBUG,  "WPS: Building WPS IE for Probe Request\n");
+    wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for Probe Request");
 
-    ie = wpabuf_alloc(400);
-    if (ie == NULL) {
-        wpa_printf(MSG_ERROR, "WPS: ie alloc failed.");
+    ie = wpabuf_alloc(500);
+    if (ie == NULL)
         return NULL;
-    }
 
     if (wps_build_version(ie) ||
         wps_build_req_type(ie, req_type) ||
         wps_build_config_methods(ie, dev->config_methods) ||
         wps_build_uuid_e(ie, uuid) ||
         wps_build_primary_dev_type(dev, ie) ||
-        wps_build_rf_bands(dev, ie) ||
+        wps_build_rf_bands(dev, ie, 0) ||
         wps_build_assoc_state(NULL, ie) ||
         wps_build_config_error(ie, WPS_CFG_NO_ERROR) ||
         wps_build_dev_password_id(ie, pw_id) ||
-#ifdef CONFIG_WPS2
         wps_build_manufacturer(dev, ie) ||
         wps_build_model_name(dev, ie) ||
         wps_build_model_number(dev, ie) ||
         wps_build_dev_name(dev, ie) ||
-        wps_build_wfa_ext(ie, req_type == WPS_REQ_ENROLLEE, NULL, 0) ||
-#endif /* CONFIG_WPS2 */
+        wps_build_wfa_ext(ie, req_type == WPS_REQ_ENROLLEE, NULL, 0, 0) ||
         wps_build_req_dev_type(dev, ie, num_req_dev_types, req_dev_types)
         ||
         wps_build_secondary_dev_type(dev, ie)
@@ -442,13 +605,6 @@ struct wpabuf * wps_build_probe_req_ie(u16 pw_id, struct wps_device_data *dev,
         return NULL;
     }
 
-#ifndef CONFIG_WPS2
-    if (dev->p2p && wps_build_dev_name(dev, ie)) {
-        wpabuf_free(ie);
-        return NULL;
-    }
-#endif /* CONFIG_WPS2 */
-
     return wps_ie_encapsulate(ie);
 }
 

+ 172 - 129
components/wpa_supplicant/src/wps/wps.h

@@ -1,6 +1,6 @@
 /*
  * Wi-Fi Protected Setup
- * Copyright (c) 2007-2012, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2007-2016, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -9,13 +9,8 @@
 #ifndef WPS_H
 #define WPS_H
 
-#if CONFIG_IDF_TARGET_ESP32
-#include "esp32/rom/ets_sys.h" // will be removed in idf v5.0
-#elif CONFIG_IDF_TARGET_ESP32S2
-#include "esp32s2/rom/ets_sys.h"
-#endif
+#include "common/ieee802_11_defs.h"
 #include "wps_defs.h"
-#include "esp_wifi_types.h"
 
 /**
  * enum wsc_op_code - EAP-WSC OP-Code values
@@ -31,6 +26,7 @@ enum wsc_op_code {
 };
 
 struct wps_registrar;
+struct upnp_wps_device_sm;
 struct wps_er;
 struct wps_parse_attr;
 
@@ -38,7 +34,7 @@ struct wps_parse_attr;
  * struct wps_credential - WPS Credential
  * @ssid: SSID
  * @ssid_len: Length of SSID
- * @auth_type: Authentication Type (WPS_WIFI_AUTH_OPEN, .. flags)
+ * @auth_type: Authentication Type (WPS_AUTH_OPEN, .. flags)
  * @encr_type: Encryption Type (WPS_ENCR_NONE, .. flags)
  * @key_idx: Key index
  * @key: Key
@@ -47,10 +43,9 @@ struct wps_parse_attr;
  * @cred_attr: Unparsed Credential attribute data (used only in cred_cb());
  *	this may be %NULL, if not used
  * @cred_attr_len: Length of cred_attr in octets
- * @ap_channel: AP channel
  */
 struct wps_credential {
-	u8 ssid[32];
+	u8 ssid[SSID_MAX_LEN];
 	size_t ssid_len;
 	u16 auth_type;
 	u16 encr_type;
@@ -60,7 +55,6 @@ struct wps_credential {
 	u8 mac_addr[ETH_ALEN];
 	const u8 *cred_attr;
 	size_t cred_attr_len;
-	u16 ap_channel;
 };
 
 #define WPS_DEV_TYPE_LEN 8
@@ -85,7 +79,7 @@ struct wps_credential {
  * @sec_dev_type: Array of secondary device types
  * @num_sec_dev_type: Number of secondary device types
  * @os_version: OS Version
- * @rf_bands: RF bands (WPS_RF_24GHZ, WPS_RF_50GHZ flags)
+ * @rf_bands: RF bands (WPS_RF_24GHZ, WPS_RF_50GHZ, WPS_RF_60GHZ flags)
  * @p2p: Whether the device is a P2P device
  */
 struct wps_device_data {
@@ -104,8 +98,10 @@ struct wps_device_data {
 	u16 config_methods;
 	struct wpabuf *vendor_ext_m1;
 	struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
+	struct wpabuf *application_ext;
 
 	int p2p;
+	u8 multi_ap_ext;
 };
 
 /**
@@ -136,7 +132,7 @@ struct wps_config {
 	 * pbc - Whether this is protocol run uses PBC
 	 */
 	int pbc;
-
+#ifndef ESP_SUPPLICANT
 	/**
 	 * assoc_wps_ie: (Re)AssocReq WPS IE (in AP; %NULL if not AP)
 	 */
@@ -166,11 +162,13 @@ struct wps_config {
 	 */
 	int use_psk_key;
 
+#endif
 	/**
 	 * dev_pw_id - Device Password ID for Enrollee when PIN is used
 	 */
 	u16 dev_pw_id;
 
+#ifndef ESP_SUPPLICANT
 	/**
 	 * p2p_dev_addr - P2P Device Address from (Re)Association Request
 	 *
@@ -188,16 +186,23 @@ struct wps_config {
 	 * PBC with the AP.
 	 */
 	int pbc_in_m1;
-};
 
-/* Bssid of the discard AP which is discarded for not select reg or other reason */
-struct discard_ap_list_t{
-	u8 bssid[6];
+	/**
+	 * peer_pubkey_hash - Peer public key hash or %NULL if not known
+	 */
+	const u8 *peer_pubkey_hash;
+
+	/**
+	 * multi_ap_backhaul_sta - Whether this is a Multi-AP backhaul STA
+	 * enrollee
+	 */
+	int multi_ap_backhaul_sta;
+#endif
 };
 
-struct wps_data * wps_init(void);
+struct wps_data * wps_init(const struct wps_config *cfg);
 
-void wps_deinit(void);
+void wps_deinit(struct wps_data *data);
 
 /**
  * enum wps_process_res - WPS message processing result
@@ -259,14 +264,15 @@ struct wps_registrar_config {
 	 * new_psk_cb - Callback for new PSK
 	 * @ctx: Higher layer context data (cb_ctx)
 	 * @mac_addr: MAC address of the Enrollee
+	 * @p2p_dev_addr: P2P Device Address of the Enrollee or all zeros if not
 	 * @psk: The new PSK
 	 * @psk_len: The length of psk in octets
 	 * Returns: 0 on success, -1 on failure
 	 *
 	 * This callback is called when a new per-device PSK is provisioned.
 	 */
-	int (*new_psk_cb)(void *ctx, const u8 *mac_addr, const u8 *psk,
-			  size_t psk_len);
+	int (*new_psk_cb)(void *ctx, const u8 *mac_addr, const u8 *p2p_dev_addr,
+			  const u8 *psk, size_t psk_len);
 
 	/**
 	 * set_ie_cb - Callback for WPS IE changes
@@ -344,6 +350,14 @@ struct wps_registrar_config {
 				 u16 dev_password_id, u8 request_type,
 				 const char *dev_name);
 
+	/**
+	 * lookup_pskfile_cb - Callback for searching for PSK in wpa_psk_file
+	 * @ctx: Higher layer context data (cb_ctx)
+	 * @addr: Enrollee's MAC address
+	 * @psk: Pointer to found PSK (output arg)
+	 */
+	int (*lookup_pskfile_cb)(void *ctx, const u8 *mac_addr, const u8 **psk);
+
 	/**
 	 * cb_ctx: Higher layer context data for Registrar callbacks
 	 */
@@ -387,14 +401,48 @@ struct wps_registrar_config {
 	int disable_auto_conf;
 
 	/**
-	 * static_wep_only - Whether the BSS supports only static WEP
+	 * dualband - Whether this is a concurrent dualband AP
 	 */
-	int static_wep_only;
+	int dualband;
 
 	/**
-	 * dualband - Whether this is a concurrent dualband AP
+	 * force_per_enrollee_psk - Force per-Enrollee random PSK
+	 *
+	 * This forces per-Enrollee random PSK to be generated even if a default
+	 * PSK is set for a network.
 	 */
-	int dualband;
+	int force_per_enrollee_psk;
+
+	/**
+	 * multi_ap_backhaul_ssid - SSID to supply to a Multi-AP backhaul
+	 * enrollee
+	 *
+	 * This SSID is used by the Registrar to fill in information for
+	 * Credentials when the enrollee advertises it is a Multi-AP backhaul
+	 * STA.
+	 */
+	const u8 *multi_ap_backhaul_ssid;
+
+	/**
+	 * multi_ap_backhaul_ssid_len - Length of multi_ap_backhaul_ssid in
+	 * octets
+	 */
+	size_t multi_ap_backhaul_ssid_len;
+
+	/**
+	 * multi_ap_backhaul_network_key - The Network Key (PSK) for the
+	 * Multi-AP backhaul enrollee.
+	 *
+	 * This key can be either the ASCII passphrase (8..63 characters) or the
+	 * 32-octet PSK (64 hex characters).
+	 */
+	const u8 *multi_ap_backhaul_network_key;
+
+	/**
+	 * multi_ap_backhaul_network_key_len - Length of
+	 * multi_ap_backhaul_network_key in octets
+	 */
+	size_t multi_ap_backhaul_network_key_len;
 };
 
 
@@ -432,6 +480,16 @@ enum wps_event {
 	 */
 	WPS_EV_PBC_TIMEOUT,
 
+	/**
+	 * WPS_EV_PBC_ACTIVE - PBC mode was activated
+	 */
+	WPS_EV_PBC_ACTIVE,
+
+	/**
+	 * WPS_EV_PBC_DISABLE - PBC mode was disabled
+	 */
+	WPS_EV_PBC_DISABLE,
+
 	/**
 	 * WPS_EV_ER_AP_ADD - ER: AP added
 	 */
@@ -500,11 +558,17 @@ union wps_event_data {
 		int msg;
 		u16 config_error;
 		u16 error_indication;
+		u8 peer_macaddr[ETH_ALEN];
 	} fail;
 
+	struct wps_event_success {
+		u8 peer_macaddr[ETH_ALEN];
+	} success;
+
 	struct wps_event_pwd_auth_fail {
 		int enrollee;
 		int part;
+		u8 peer_macaddr[ETH_ALEN];
 	} pwd_auth_fail;
 
 	struct wps_event_er_ap {
@@ -568,7 +632,6 @@ struct upnp_pending_message {
 	struct wpabuf *msg;
 	enum wps_msg_type type;
 };
-void wps_free_pending_msgs(struct upnp_pending_message *msgs);
 #endif
 /**
  * struct wps_context - Long term WPS context data
@@ -609,7 +672,7 @@ struct wps_context {
 	 * Credentials. In addition, AP uses it when acting as an Enrollee to
 	 * notify Registrar of the current configuration.
 	 */
-	u8 ssid[32];
+	u8 ssid[SSID_MAX_LEN];
 
 	/**
 	 * ssid_len - Length of ssid in octets
@@ -648,11 +711,31 @@ struct wps_context {
 	 */
 	u16 encr_types;
 
+	/**
+	 * encr_types_rsn - Enabled encryption types for RSN (WPS_ENCR_*)
+	 */
+	u16 encr_types_rsn;
+
+	/**
+	 * encr_types_wpa - Enabled encryption types for WPA (WPS_ENCR_*)
+	 */
+	u16 encr_types_wpa;
+
 	/**
 	 * auth_types - Authentication types (bit field of WPS_AUTH_*)
 	 */
 	u16 auth_types;
 
+	/**
+	 * encr_types - Current AP encryption type (WPS_ENCR_*)
+	 */
+	u16 ap_encr_type;
+
+	/**
+	 * ap_auth_type - Current AP authentication types (WPS_AUTH_*)
+	 */
+	u16 ap_auth_type;
+
 	/**
 	 * network_key - The current Network Key (PSK) or %NULL to generate new
 	 *
@@ -660,7 +743,7 @@ struct wps_context {
 	 * uses this when acting as an Enrollee to notify Registrar of the
 	 * current configuration.
 	 *
-	 * When using WPA/WPA2-Person, this key can be either the ASCII
+	 * When using WPA/WPA2-Personal, this key can be either the ASCII
 	 * passphrase (8..63 characters) or the 32-octet PSK (64 hex
 	 * characters). When this is set to the ASCII passphrase, the PSK can
 	 * be provided in the psk buffer and used per-Enrollee to control which
@@ -743,35 +826,43 @@ struct wps_context {
 	void (*event_cb)(void *ctx, enum wps_event event,
 			 union wps_event_data *data);
 
+	/**
+	 * rf_band_cb - Fetch currently used RF band
+	 * @ctx: Higher layer context data (cb_ctx)
+	 * Return: Current used RF band or 0 if not known
+	 */
+	int (*rf_band_cb)(void *ctx);
+
 	/**
 	 * cb_ctx: Higher layer context data for callbacks
 	 */
 	void *cb_ctx;
 
+	struct upnp_wps_device_sm *wps_upnp;
+
 	/* Pending messages from UPnP PutWLANResponse */
-#ifdef CONFIG_WPS_NFC
+	struct upnp_pending_message *upnp_msgs;
 
 	u16 ap_nfc_dev_pw_id;
 	struct wpabuf *ap_nfc_dh_pubkey;
 	struct wpabuf *ap_nfc_dh_privkey;
 	struct wpabuf *ap_nfc_dev_pw;
-#endif
+
+	/* Whether to send WPA2-PSK passphrase as a passphrase instead of PSK
+	 * for WPA3-Personal transition mode needs. */
+	bool use_passphrase;
 };
 
 struct wps_registrar *
 wps_registrar_init(struct wps_context *wps,
 		   const struct wps_registrar_config *cfg);
 void wps_registrar_deinit(struct wps_registrar *reg);
-#ifdef CONFIG_WPS_PIN
-
 int wps_registrar_add_pin(struct wps_registrar *reg, const u8 *addr,
 			  const u8 *uuid, const u8 *pin, size_t pin_len,
 			  int timeout);
 int wps_registrar_invalidate_pin(struct wps_registrar *reg, const u8 *uuid);
-int wps_registrar_unlock_pin(struct wps_registrar *reg, const u8 *uuid);
-#endif
 int wps_registrar_wps_cancel(struct wps_registrar *reg);
-
+int wps_registrar_unlock_pin(struct wps_registrar *reg, const u8 *uuid);
 int wps_registrar_button_pushed(struct wps_registrar *reg,
 				const u8 *p2p_dev_addr);
 void wps_registrar_complete(struct wps_registrar *registrar, const u8 *uuid_e,
@@ -788,27 +879,35 @@ int wps_registrar_config_ap(struct wps_registrar *reg,
 
 int wps_registrar_add_nfc_pw_token(struct wps_registrar *reg,
 				   const u8 *pubkey_hash, u16 pw_id,
-				   const u8 *dev_pw, size_t dev_pw_len);
+				   const u8 *dev_pw, size_t dev_pw_len,
+				   int pk_hash_provided_oob);
 int wps_registrar_add_nfc_password_token(struct wps_registrar *reg,
 					 const u8 *oob_dev_pw,
 					 size_t oob_dev_pw_len);
 #endif
+void wps_registrar_flush(struct wps_registrar *reg);
+int wps_registrar_update_multi_ap(struct wps_registrar *reg,
+				  const u8 *multi_ap_backhaul_ssid,
+				  size_t multi_ap_backhaul_ssid_len,
+				  const u8 *multi_ap_backhaul_network_key,
+				  size_t multi_ap_backhaul_network_key_len);
+
 int wps_build_credential_wrap(struct wpabuf *msg,
 			      const struct wps_credential *cred);
-#ifdef CONFIG_WPS_PIN
+
 unsigned int wps_pin_checksum(unsigned int pin);
 unsigned int wps_pin_valid(unsigned int pin);
+int wps_generate_pin(unsigned int *pin);
 int wps_pin_str_valid(const char *pin);
-#endif
-
-unsigned int wps_generate_pin(void);
+void wps_free_pending_msgs(struct upnp_pending_message *msgs);
 
 #ifdef CONFIG_WPS_OOB
-
-struct wpabuf * wps_get_oob_cred(struct wps_context *wps);
+struct wpabuf * wps_get_oob_cred(struct wps_context *wps, int rf_band,
+				 int channel);
 int wps_oob_use_cred(struct wps_context *wps, struct wps_parse_attr *attr);
 #endif
 int wps_attr_text(struct wpabuf *data, char *buf, char *end);
+const char * wps_ei_str(enum wps_error_indication ei);
 
 struct wps_er * wps_er_init(struct wps_context *wps, const char *ifname,
 			    const char *filter);
@@ -816,18 +915,22 @@ void wps_er_refresh(struct wps_er *er);
 void wps_er_deinit(struct wps_er *er, void (*cb)(void *ctx), void *ctx);
 void wps_er_set_sel_reg(struct wps_er *er, int sel_reg, u16 dev_passwd_id,
 			u16 sel_reg_config_methods);
-int wps_er_pbc(struct wps_er *er, const u8 *uuid);
-int wps_er_learn(struct wps_er *er, const u8 *uuid, const u8 *pin,
-		 size_t pin_len);
-int wps_er_set_config(struct wps_er *er, const u8 *uuid,
+int wps_er_pbc(struct wps_er *er, const u8 *uuid, const u8 *addr);
+const u8 * wps_er_get_sta_uuid(struct wps_er *er, const u8 *addr);
+int wps_er_learn(struct wps_er *er, const u8 *uuid, const u8 *addr,
+		 const u8 *pin, size_t pin_len);
+int wps_er_set_config(struct wps_er *er, const u8 *uuid, const u8 *addr,
 		      const struct wps_credential *cred);
-int wps_er_config(struct wps_er *er, const u8 *uuid, const u8 *pin,
-		  size_t pin_len, const struct wps_credential *cred);
-#ifdef CONFIG_WPS_NFC
-
-struct wpabuf * wps_er_nfc_config_token(struct wps_er *er, const u8 *uuid);
-
-#endif
+int wps_er_config(struct wps_er *er, const u8 *uuid, const u8 *addr,
+		  const u8 *pin, size_t pin_len,
+		  const struct wps_credential *cred);
+struct wpabuf * wps_er_config_token_from_cred(struct wps_context *wps,
+					      struct wps_credential *cred);
+struct wpabuf * wps_er_nfc_config_token(struct wps_er *er, const u8 *uuid,
+					const u8 *addr);
+struct wpabuf * wps_er_nfc_handover_sel(struct wps_er *er,
+					struct wps_context *wps, const u8 *uuid,
+					const u8 *addr, struct wpabuf *pubkey);
 
 int wps_dev_type_str2bin(const char *str, u8 dev_type[WPS_DEV_TYPE_LEN]);
 char * wps_dev_type_bin2str(const u8 dev_type[WPS_DEV_TYPE_LEN], char *buf,
@@ -840,15 +943,30 @@ u16 wps_config_methods_str2bin(const char *str);
 struct wpabuf * wps_build_nfc_pw_token(u16 dev_pw_id,
 				       const struct wpabuf *pubkey,
 				       const struct wpabuf *dev_pw);
+struct wpabuf * wps_nfc_token_build(int ndef, int id, struct wpabuf *pubkey,
+				    struct wpabuf *dev_pw);
+int wps_nfc_gen_dh(struct wpabuf **pubkey, struct wpabuf **privkey);
 struct wpabuf * wps_nfc_token_gen(int ndef, int *id, struct wpabuf **pubkey,
 				  struct wpabuf **privkey,
 				  struct wpabuf **dev_pw);
+struct wpabuf * wps_build_nfc_handover_req(struct wps_context *ctx,
+					   struct wpabuf *nfc_dh_pubkey);
+struct wpabuf * wps_build_nfc_handover_sel(struct wps_context *ctx,
+					   struct wpabuf *nfc_dh_pubkey,
+					   const u8 *bssid, int freq);
+struct wpabuf * wps_build_nfc_handover_req_p2p(struct wps_context *ctx,
+					       struct wpabuf *nfc_dh_pubkey);
+struct wpabuf * wps_build_nfc_handover_sel_p2p(struct wps_context *ctx,
+					       int nfc_dev_pw_id,
+					       struct wpabuf *nfc_dh_pubkey,
+					       struct wpabuf *nfc_dev_pw);
 #endif
 
 /* ndef.c */
 struct wpabuf * ndef_parse_wifi(const struct wpabuf *buf);
 struct wpabuf * ndef_build_wifi(const struct wpabuf *buf);
-struct wpabuf * ndef_build_wifi_hr(void);
+struct wpabuf * ndef_parse_p2p(const struct wpabuf *buf);
+struct wpabuf * ndef_build_p2p(const struct wpabuf *buf);
 
 #ifdef CONFIG_WPS_STRICT
 int wps_validate_beacon(const struct wpabuf *wps_ie);
@@ -996,79 +1114,4 @@ static inline int wps_validate_upnp_set_selected_registrar(
 }
 #endif /* CONFIG_WPS_STRICT */
 
-enum wps_cb_status {
-	WPS_CB_ST_SUCCESS = 0,
-	WPS_CB_ST_FAILED,
-	WPS_CB_ST_TIMEOUT,
-	WPS_CB_ST_WEP,
-	WPS_CB_ST_SCAN_ERR,
-};
-
-typedef void (*wps_st_cb_t)(int status);
-
-#ifdef USE_WPS_TASK
-enum wps_sig_type {
-    SIG_WPS_ENABLE = 1,         //1
-    SIG_WPS_DISABLE,            //2
-    SIG_WPS_START,              //3
-    SIG_WPS_RX,                 //4
-    SIG_WPS_TIMER_TIMEOUT,      //5
-    SIG_WPS_TIMER_MSG_TIMEOUT,  //6
-    SIG_WPS_TIMER_SUCCESS_CB,   //7
-    SIG_WPS_TIMER_SCAN,         //8
-    SIG_WPS_TIMER_EAPOL_START,  //9
-    SIG_WPS_NUM,                //10
-};
-#endif
-
-#define WPS_EAP_EXT_VENDOR_TYPE "WFA-SimpleConfig-Enrollee-1-0"
-#define WPS_OUTBUF_SIZE 500
-struct wps_sm {
-    struct wps_config *wps_cfg;
-    struct wps_context *wps_ctx;
-    struct wps_data *wps;
-    char identity[32];
-    u8 identity_len;
-    u8 ownaddr[ETH_ALEN];
-    u8 bssid[ETH_ALEN];
-    u8 ssid[MAX_WPS_AP_CRED][MAX_SSID_LEN];
-    u8 ssid_len[MAX_WPS_AP_CRED];
-    char key[MAX_WPS_AP_CRED][MAX_PASSPHRASE_LEN];
-    u8 key_len[MAX_WPS_AP_CRED];
-    u8 ap_cred_cnt;
-    struct wps_device_data *dev;
-    u8 uuid[16];
-    u8 eapol_version;
-    ETSTimer wps_timeout_timer;
-    ETSTimer wps_msg_timeout_timer;
-    ETSTimer wps_scan_timer;
-    ETSTimer wps_success_cb_timer;
-    ETSTimer wps_eapol_start_timer;
-    wps_st_cb_t st_cb;
-    u8 current_identifier;
-    bool is_wps_scan;
-    u8 channel;
-    u8 scan_cnt;
-#ifdef USE_WPS_TASK
-    u8 wps_sig_cnt[SIG_WPS_NUM];
-#endif
-    u8 discover_ssid_cnt;
-    bool ignore_sel_reg;
-    bool wps_pin_war;
-    struct discard_ap_list_t dis_ap_list[WPS_MAX_DIS_AP_NUM];
-    u8 discard_ap_cnt;
-    wifi_sta_config_t config;
-};
-
-#define    WIFI_CAPINFO_PRIVACY        0x0010
-
-struct wps_sm *wps_sm_get(void);
-int wps_ssid_save(u8 *ssid, u8 ssid_len, u8 idx);
-int wps_key_save(char *key, u8 key_len, u8 idx);
-int wps_station_wps_register_cb(wps_st_cb_t cb);
-int wps_station_wps_unregister_cb(void);
-int wps_start_pending(void);
-int wps_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len);
-
-int wps_dev_deinit(struct wps_device_data *dev);
 #endif /* WPS_H */

+ 210 - 98
components/wpa_supplicant/src/wps/wps_attr_build.c

@@ -1,86 +1,99 @@
 /*
  * Wi-Fi Protected Setup - attribute building
- * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2008-2016, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
  */
-#include "utils/includes.h"
-#include "utils/common.h"
-#include "utils/wpa_debug.h"
 
+#include "includes.h"
+
+#include "common.h"
 #include "crypto/aes_wrap.h"
 #include "crypto/crypto.h"
+#include "crypto/dh_group5.h"
 #include "crypto/sha256.h"
 #include "crypto/random.h"
-#include "crypto/dh_group5.h"
-
 #include "common/ieee802_11_defs.h"
-#include "wps/wps_i.h"
+#include "wps_i.h"
+
 
-int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg, wps_key_mode_t mode)
+int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg)
 {
 	struct wpabuf *pubkey = NULL;
 
-	if (mode != WPS_CALC_KEY_NO_CALC) {
-
-		wpa_printf(MSG_DEBUG,  "WPS:  * Public Key");
-		wpabuf_free(wps->dh_privkey);
-		if (wps->dev_pw_id != DEV_PW_DEFAULT && wps->wps->dh_privkey) {
-			wpa_printf(MSG_DEBUG,  "WPS: Using pre-configured DH keys");
-			wps->dh_privkey = wpabuf_dup(wps->wps->dh_privkey);
-			wps->dh_ctx = wps->wps->dh_ctx;
-			wps->wps->dh_ctx = NULL;
-			pubkey = wpabuf_dup(wps->wps->dh_pubkey);
-#ifdef CONFIG_WPS_NFC
-		} else if (wps->dev_pw_id >= 0x10 && wps->wps->ap &&
-				wps->dev_pw_id == wps->wps->ap_nfc_dev_pw_id) {
-			wpa_printf(MSG_DEBUG,  "WPS: Using NFC password token DH keys");
-			wps->dh_privkey = wpabuf_dup(wps->wps->ap_nfc_dh_privkey);
-			pubkey = wpabuf_dup(wps->wps->ap_nfc_dh_pubkey);
-			wps->dh_ctx = dh5_init_fixed(wps->dh_privkey, pubkey);
-#endif /* CONFIG_WPS_NFC */
-		} else {
-			wpa_printf(MSG_DEBUG,  "WPS: Generate new DH keys");
-			wps->dh_privkey = NULL;
-			dh5_free(wps->dh_ctx);
-
-			wpa_printf(MSG_DEBUG, "build public key start\n");
-
-			wps->dh_ctx = dh5_init(&wps->dh_privkey, &pubkey);
-
-			wpa_printf(MSG_DEBUG, "build public key finish\n");
-
-			pubkey = wpabuf_zeropad(pubkey, 192);
+	wpa_printf(MSG_DEBUG, "WPS:  * Public Key");
+	wpabuf_clear_free(wps->dh_privkey);
+	wps->dh_privkey = NULL;
+	if (wps->dev_pw_id != DEV_PW_DEFAULT && wps->wps->dh_privkey &&
+	    wps->wps->dh_ctx) {
+		wpa_printf(MSG_DEBUG, "WPS: Using pre-configured DH keys");
+		if (wps->wps->dh_pubkey == NULL) {
+			wpa_printf(MSG_DEBUG,
+				   "WPS: wps->wps->dh_pubkey == NULL");
+			return -1;
 		}
-		if (wps->dh_ctx == NULL || wps->dh_privkey == NULL || pubkey == NULL) {
-			wpa_printf(MSG_DEBUG,  "WPS: Failed to initialize "
-					"Diffie-Hellman handshake");
-			wpabuf_free(pubkey);
+		wps->dh_privkey = wpabuf_dup(wps->wps->dh_privkey);
+		wps->dh_ctx = wps->wps->dh_ctx;
+		wps->wps->dh_ctx = NULL;
+		pubkey = wpabuf_dup(wps->wps->dh_pubkey);
+#ifdef CONFIG_WPS_NFC
+	} else if ((wps->dev_pw_id >= 0x10 ||
+		    wps->dev_pw_id == DEV_PW_NFC_CONNECTION_HANDOVER) &&
+		   (wps->wps->ap ||
+		    (wps->wps->ap_nfc_dh_pubkey &&
+		     wps->wps->ap_nfc_dev_pw_id ==
+		     DEV_PW_NFC_CONNECTION_HANDOVER &&
+		     wps->dev_pw_id == DEV_PW_NFC_CONNECTION_HANDOVER)) &&
+		   (wps->dev_pw_id == wps->wps->ap_nfc_dev_pw_id ||
+		    wps->wps->ap_nfc_dh_pubkey)) {
+		wpa_printf(MSG_DEBUG, "WPS: Using NFC password token DH keys");
+		if (wps->wps->ap_nfc_dh_privkey == NULL) {
+			wpa_printf(MSG_DEBUG,
+				   "WPS: wps->wps->ap_nfc_dh_privkey == NULL");
 			return -1;
 		}
-		wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH Private Key", wps->dh_privkey);
-		wpa_hexdump_buf(MSG_DEBUG, "WPS: DH own Public Key", pubkey);
-
-		if (wps->registrar) {
-			wpabuf_free(wps->dh_pubkey_r);
-			wps->dh_pubkey_r = pubkey;
-		} else {
-			wpabuf_free(wps->dh_pubkey_e);
-			wps->dh_pubkey_e = pubkey;
+		if (wps->wps->ap_nfc_dh_pubkey == NULL) {
+			wpa_printf(MSG_DEBUG,
+				   "WPS: wps->wps->ap_nfc_dh_pubkey == NULL");
+			return -1;
 		}
-
+		wps->dh_privkey = wpabuf_dup(wps->wps->ap_nfc_dh_privkey);
+		pubkey = wpabuf_dup(wps->wps->ap_nfc_dh_pubkey);
+		if (wps->dh_privkey && pubkey)
+			wps->dh_ctx = dh5_init_fixed(wps->dh_privkey, pubkey);
+#endif /* CONFIG_WPS_NFC */
+	} else {
+		wpa_printf(MSG_DEBUG, "WPS: Generate new DH keys");
+		dh5_free(wps->dh_ctx);
+		wps->dh_ctx = dh5_init(&wps->dh_privkey, &pubkey);
+		pubkey = wpabuf_zeropad(pubkey, 192);
 	}
-
-	if (mode != WPS_CALC_KEY_PRE_CALC) {
-		if (wps->registrar)
-			pubkey = wps->dh_pubkey_r;
-		else
-			pubkey = wps->dh_pubkey_e;
-
-		wpabuf_put_be16(msg, ATTR_PUBLIC_KEY);
-		wpabuf_put_be16(msg, wpabuf_len(pubkey));
-		wpabuf_put_buf(msg, pubkey);
+	if (wps->dh_ctx == NULL || wps->dh_privkey == NULL || pubkey == NULL) {
+		wpa_printf(MSG_DEBUG, "WPS: Failed to initialize "
+			   "Diffie-Hellman handshake");
+		wpabuf_free(pubkey);
+		return -1;
+	}
+	wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH Private Key", wps->dh_privkey);
+	wpa_hexdump_buf(MSG_DEBUG, "WPS: DH own Public Key", pubkey);
+
+#ifdef ESP_SUPPLICANT
+	if (msg) {
+#endif
+	wpabuf_put_be16(msg, ATTR_PUBLIC_KEY);
+	wpabuf_put_be16(msg, wpabuf_len(pubkey));
+	wpabuf_put_buf(msg, pubkey);
+#ifdef ESP_SUPPLICANT
+	}
+#endif
+
+	if (wps->registrar) {
+		wpabuf_free(wps->dh_pubkey_r);
+		wps->dh_pubkey_r = pubkey;
+	} else {
+		wpabuf_free(wps->dh_pubkey_e);
+		wps->dh_pubkey_e = pubkey;
 	}
 
 	return 0;
@@ -89,7 +102,7 @@ int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg, wps_key_mode_
 
 int wps_build_req_type(struct wpabuf *msg, enum wps_request_type type)
 {
-	wpa_printf(MSG_DEBUG,  "WPS:  * Request Type");
+	wpa_printf(MSG_DEBUG, "WPS:  * Request Type");
 	wpabuf_put_be16(msg, ATTR_REQUEST_TYPE);
 	wpabuf_put_be16(msg, 1);
 	wpabuf_put_u8(msg, type);
@@ -99,7 +112,7 @@ int wps_build_req_type(struct wpabuf *msg, enum wps_request_type type)
 
 int wps_build_resp_type(struct wpabuf *msg, enum wps_response_type type)
 {
-	wpa_printf(MSG_DEBUG,  "WPS:  * Response Type (%d)", type);
+	wpa_printf(MSG_DEBUG, "WPS:  * Response Type (%d)", type);
 	wpabuf_put_be16(msg, ATTR_RESPONSE_TYPE);
 	wpabuf_put_be16(msg, 1);
 	wpabuf_put_u8(msg, type);
@@ -109,7 +122,7 @@ int wps_build_resp_type(struct wpabuf *msg, enum wps_response_type type)
 
 int wps_build_config_methods(struct wpabuf *msg, u16 methods)
 {
-	wpa_printf(MSG_DEBUG,  "WPS:  * Config Methods (%x)", methods);
+	wpa_printf(MSG_DEBUG, "WPS:  * Config Methods (%x)", methods);
 	wpabuf_put_be16(msg, ATTR_CONFIG_METHODS);
 	wpabuf_put_be16(msg, 2);
 	wpabuf_put_be16(msg, methods);
@@ -119,7 +132,9 @@ int wps_build_config_methods(struct wpabuf *msg, u16 methods)
 
 int wps_build_uuid_e(struct wpabuf *msg, const u8 *uuid)
 {
-	wpa_printf(MSG_DEBUG,  "WPS:  * UUID-E");
+	if (wpabuf_tailroom(msg) < 4 + WPS_UUID_LEN)
+		return -1;
+	wpa_printf(MSG_DEBUG, "WPS:  * UUID-E");
 	wpabuf_put_be16(msg, ATTR_UUID_E);
 	wpabuf_put_be16(msg, WPS_UUID_LEN);
 	wpabuf_put_data(msg, uuid, WPS_UUID_LEN);
@@ -129,7 +144,7 @@ int wps_build_uuid_e(struct wpabuf *msg, const u8 *uuid)
 
 int wps_build_dev_password_id(struct wpabuf *msg, u16 id)
 {
-	wpa_printf(MSG_DEBUG,  "WPS:  * Device Password ID (%d)", id);
+	wpa_printf(MSG_DEBUG, "WPS:  * Device Password ID (%d)", id);
 	wpabuf_put_be16(msg, ATTR_DEV_PASSWORD_ID);
 	wpabuf_put_be16(msg, 2);
 	wpabuf_put_be16(msg, id);
@@ -139,7 +154,7 @@ int wps_build_dev_password_id(struct wpabuf *msg, u16 id)
 
 int wps_build_config_error(struct wpabuf *msg, u16 err)
 {
-	wpa_printf(MSG_DEBUG,  "WPS:  * Configuration Error (%d)", err);
+	wpa_printf(MSG_DEBUG, "WPS:  * Configuration Error (%d)", err);
 	wpabuf_put_be16(msg, ATTR_CONFIG_ERROR);
 	wpabuf_put_be16(msg, 2);
 	wpabuf_put_be16(msg, err);
@@ -154,7 +169,7 @@ int wps_build_authenticator(struct wps_data *wps, struct wpabuf *msg)
 	size_t len[2];
 
 	if (wps->last_msg == NULL) {
-		wpa_printf(MSG_DEBUG,  "WPS: Last message not available for "
+		wpa_printf(MSG_DEBUG, "WPS: Last message not available for "
 			   "building authenticator");
 		return -1;
 	}
@@ -166,8 +181,11 @@ int wps_build_authenticator(struct wps_data *wps, struct wpabuf *msg)
 	len[0] = wpabuf_len(wps->last_msg);
 	addr[1] = wpabuf_head(msg);
 	len[1] = wpabuf_len(msg);
-	hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 2, addr, len, hash);
-	wpa_printf(MSG_DEBUG,  "WPS:  * Authenticator");
+	if (hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 2, addr, len,
+			       hash) < 0)
+		return -1;
+
+	wpa_printf(MSG_DEBUG, "WPS:  * Authenticator");
 	wpabuf_put_be16(msg, ATTR_AUTHENTICATOR);
 	wpabuf_put_be16(msg, WPS_AUTHENTICATOR_LEN);
 	wpabuf_put_data(msg, hash, WPS_AUTHENTICATOR_LEN);
@@ -183,7 +201,9 @@ int wps_build_version(struct wpabuf *msg)
 	 * backwards compatibility reasons. The real version negotiation is
 	 * done with Version2.
 	 */
-	wpa_printf(MSG_DEBUG,  "WPS:  * Version (hardcoded 0x10)");
+	if (wpabuf_tailroom(msg) < 5)
+		return -1;
+	wpa_printf(MSG_DEBUG, "WPS:  * Version (hardcoded 0x10)");
 	wpabuf_put_be16(msg, ATTR_VERSION);
 	wpabuf_put_be16(msg, 1);
 	wpabuf_put_u8(msg, 0x10);
@@ -192,22 +212,31 @@ int wps_build_version(struct wpabuf *msg)
 
 
 int wps_build_wfa_ext(struct wpabuf *msg, int req_to_enroll,
-		      const u8 *auth_macs, size_t auth_macs_count)
+		      const u8 *auth_macs, size_t auth_macs_count,
+		      u8 multi_ap_subelem)
 {
-#ifdef CONFIG_WPS2
 	u8 *len;
 
+#ifdef CONFIG_WPS_TESTING
+	if (WPS_VERSION == 0x10)
+		return 0;
+#endif /* CONFIG_WPS_TESTING */
+
+	if (wpabuf_tailroom(msg) <
+	    7 + 3 + (req_to_enroll ? 3 : 0) +
+	    (auth_macs ? 2 + auth_macs_count * ETH_ALEN : 0))
+		return -1;
 	wpabuf_put_be16(msg, ATTR_VENDOR_EXT);
 	len = wpabuf_put(msg, 2); /* to be filled */
 	wpabuf_put_be24(msg, WPS_VENDOR_ID_WFA);
 
-	wpa_printf(MSG_DEBUG,  "WPS:  * Version2 (0x%x)", WPS_VERSION);
+	wpa_printf(MSG_DEBUG, "WPS:  * Version2 (0x%x)", WPS_VERSION);
 	wpabuf_put_u8(msg, WFA_ELEM_VERSION2);
 	wpabuf_put_u8(msg, 1);
 	wpabuf_put_u8(msg, WPS_VERSION);
 
 	if (req_to_enroll) {
-		wpa_printf(MSG_DEBUG,  "WPS:  * Request to Enroll (1)");
+		wpa_printf(MSG_DEBUG, "WPS:  * Request to Enroll (1)");
 		wpabuf_put_u8(msg, WFA_ELEM_REQUEST_TO_ENROLL);
 		wpabuf_put_u8(msg, 1);
 		wpabuf_put_u8(msg, 1);
@@ -215,22 +244,31 @@ int wps_build_wfa_ext(struct wpabuf *msg, int req_to_enroll,
 
 	if (auth_macs && auth_macs_count) {
 		size_t i;
-		wpa_printf(MSG_DEBUG,  "WPS:  * AuthorizedMACs (count=%d)",
+		wpa_printf(MSG_DEBUG, "WPS:  * AuthorizedMACs (count=%d)",
 			   (int) auth_macs_count);
 		wpabuf_put_u8(msg, WFA_ELEM_AUTHORIZEDMACS);
 		wpabuf_put_u8(msg, auth_macs_count * ETH_ALEN);
 		wpabuf_put_data(msg, auth_macs, auth_macs_count * ETH_ALEN);
 		for (i = 0; i < auth_macs_count; i++)
-			wpa_printf(MSG_DEBUG,  "WPS:    AuthorizedMAC: " MACSTR,
+			wpa_printf(MSG_DEBUG, "WPS:    AuthorizedMAC: " MACSTR,
 				   MAC2STR(&auth_macs[i * ETH_ALEN]));
 	}
 
+	if (multi_ap_subelem) {
+		wpa_printf(MSG_DEBUG, "WPS:  * Multi-AP (0x%x)",
+			   multi_ap_subelem);
+		wpabuf_put_u8(msg, WFA_ELEM_MULTI_AP);
+		wpabuf_put_u8(msg, 1); /* length */
+		wpabuf_put_u8(msg, multi_ap_subelem);
+	}
+
 	WPA_PUT_BE16(len, (u8 *) wpabuf_put(msg, 0) - len - 2);
-#endif /* CONFIG_WPS2 */
 
 #ifdef CONFIG_WPS_TESTING
 	if (WPS_VERSION > 0x20) {
-		wpa_printf(MSG_DEBUG,  "WPS:  * Extensibility Testing - extra "
+		if (wpabuf_tailroom(msg) < 5)
+			return -1;
+		wpa_printf(MSG_DEBUG, "WPS:  * Extensibility Testing - extra "
 			   "attribute");
 		wpabuf_put_be16(msg, ATTR_EXTENSIBILITY_TEST);
 		wpabuf_put_be16(msg, 1);
@@ -243,7 +281,7 @@ int wps_build_wfa_ext(struct wpabuf *msg, int req_to_enroll,
 
 int wps_build_msg_type(struct wpabuf *msg, enum wps_msg_type msg_type)
 {
-	wpa_printf(MSG_DEBUG,  "WPS:  * Message Type (%d)", msg_type);
+	wpa_printf(MSG_DEBUG, "WPS:  * Message Type (%d)", msg_type);
 	wpabuf_put_be16(msg, ATTR_MSG_TYPE);
 	wpabuf_put_be16(msg, 1);
 	wpabuf_put_u8(msg, msg_type);
@@ -253,7 +291,7 @@ int wps_build_msg_type(struct wpabuf *msg, enum wps_msg_type msg_type)
 
 int wps_build_enrollee_nonce(struct wps_data *wps, struct wpabuf *msg)
 {
-	wpa_printf(MSG_DEBUG,  "WPS:  * Enrollee Nonce");
+	wpa_printf(MSG_DEBUG, "WPS:  * Enrollee Nonce");
 	wpabuf_put_be16(msg, ATTR_ENROLLEE_NONCE);
 	wpabuf_put_be16(msg, WPS_NONCE_LEN);
 	wpabuf_put_data(msg, wps->nonce_e, WPS_NONCE_LEN);
@@ -263,7 +301,7 @@ int wps_build_enrollee_nonce(struct wps_data *wps, struct wpabuf *msg)
 
 int wps_build_registrar_nonce(struct wps_data *wps, struct wpabuf *msg)
 {
-	wpa_printf(MSG_DEBUG,  "WPS:  * Registrar Nonce");
+	wpa_printf(MSG_DEBUG, "WPS:  * Registrar Nonce");
 	wpabuf_put_be16(msg, ATTR_REGISTRAR_NONCE);
 	wpabuf_put_be16(msg, WPS_NONCE_LEN);
 	wpabuf_put_data(msg, wps->nonce_r, WPS_NONCE_LEN);
@@ -274,10 +312,23 @@ int wps_build_registrar_nonce(struct wps_data *wps, struct wpabuf *msg)
 int wps_build_auth_type_flags(struct wps_data *wps, struct wpabuf *msg)
 {
 	u16 auth_types = WPS_AUTH_TYPES;
-#ifdef CONFIG_WPS2
+	/* WPA/WPA2-Enterprise enrollment not supported through WPS */
+	auth_types &= ~WPS_AUTH_WPA;
+	auth_types &= ~WPS_AUTH_WPA2;
 	auth_types &= ~WPS_AUTH_SHARED;
-#endif /* CONFIG_WPS2 */
-	wpa_printf(MSG_DEBUG,  "WPS:  * Authentication Type Flags");
+#ifdef CONFIG_NO_TKIP
+	auth_types &= ~WPS_AUTH_WPAPSK;
+#endif /* CONFIG_NO_TKIP */
+#ifdef CONFIG_WPS_TESTING
+	if (wps_force_auth_types_in_use) {
+		wpa_printf(MSG_DEBUG,
+			   "WPS: Testing - replace auth type 0x%x with 0x%x",
+			   auth_types, wps_force_auth_types);
+		auth_types = wps_force_auth_types;
+	}
+#endif /* CONFIG_WPS_TESTING */
+	wpa_printf(MSG_DEBUG, "WPS:  * Authentication Type Flags (0x%x)",
+		   auth_types);
 	wpabuf_put_be16(msg, ATTR_AUTH_TYPE_FLAGS);
 	wpabuf_put_be16(msg, 2);
 	wpabuf_put_be16(msg, auth_types);
@@ -288,10 +339,20 @@ int wps_build_auth_type_flags(struct wps_data *wps, struct wpabuf *msg)
 int wps_build_encr_type_flags(struct wps_data *wps, struct wpabuf *msg)
 {
 	u16 encr_types = WPS_ENCR_TYPES;
-#ifdef CONFIG_WPS2
 	encr_types &= ~WPS_ENCR_WEP;
-#endif /* CONFIG_WPS2 */
-	wpa_printf(MSG_DEBUG,  "WPS:  * Encryption Type Flags");
+#ifdef CONFIG_NO_TKIP
+	encr_types &= ~WPS_ENCR_TKIP;
+#endif /* CONFIG_NO_TKIP */
+#ifdef CONFIG_WPS_TESTING
+	if (wps_force_encr_types_in_use) {
+		wpa_printf(MSG_DEBUG,
+			   "WPS: Testing - replace encr type 0x%x with 0x%x",
+			   encr_types, wps_force_encr_types);
+		encr_types = wps_force_encr_types;
+	}
+#endif /* CONFIG_WPS_TESTING */
+	wpa_printf(MSG_DEBUG, "WPS:  * Encryption Type Flags (0x%x)",
+		   encr_types);
 	wpabuf_put_be16(msg, ATTR_ENCR_TYPE_FLAGS);
 	wpabuf_put_be16(msg, 2);
 	wpabuf_put_be16(msg, encr_types);
@@ -301,7 +362,7 @@ int wps_build_encr_type_flags(struct wps_data *wps, struct wpabuf *msg)
 
 int wps_build_conn_type_flags(struct wps_data *wps, struct wpabuf *msg)
 {
-	wpa_printf(MSG_DEBUG,  "WPS:  * Connection Type Flags");
+	wpa_printf(MSG_DEBUG, "WPS:  * Connection Type Flags");
 	wpabuf_put_be16(msg, ATTR_CONN_TYPE_FLAGS);
 	wpabuf_put_be16(msg, 1);
 	wpabuf_put_u8(msg, WPS_CONN_ESS);
@@ -311,7 +372,7 @@ int wps_build_conn_type_flags(struct wps_data *wps, struct wpabuf *msg)
 
 int wps_build_assoc_state(struct wps_data *wps, struct wpabuf *msg)
 {
-	wpa_printf(MSG_DEBUG,  "WPS:  * Association State");
+	wpa_printf(MSG_DEBUG, "WPS:  * Association State");
 	wpabuf_put_be16(msg, ATTR_ASSOC_STATE);
 	wpabuf_put_be16(msg, 2);
 	wpabuf_put_be16(msg, WPS_ASSOC_NOT_ASSOC);
@@ -323,9 +384,11 @@ int wps_build_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg)
 {
 	u8 hash[SHA256_MAC_LEN];
 
-	wpa_printf(MSG_DEBUG,  "WPS:  * Key Wrap Authenticator");
-	hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, wpabuf_head(msg),
-		            wpabuf_len(msg), hash);
+	wpa_printf(MSG_DEBUG, "WPS:  * Key Wrap Authenticator");
+	if (hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, wpabuf_head(msg),
+			wpabuf_len(msg), hash) < 0)
+		return -1;
+
 	wpabuf_put_be16(msg, ATTR_KEY_WRAP_AUTH);
 	wpabuf_put_be16(msg, WPS_KWA_LEN);
 	wpabuf_put_data(msg, hash, WPS_KWA_LEN);
@@ -340,7 +403,7 @@ int wps_build_encr_settings(struct wps_data *wps, struct wpabuf *msg,
 	const size_t block_size = 16;
 	u8 *iv, *data;
 
-	wpa_printf(MSG_DEBUG,  "WPS:  * Encrypted Settings");
+	wpa_printf(MSG_DEBUG, "WPS:  * Encrypted Settings");
 
 	/* PKCS#5 v2.0 pad */
 	pad_len = block_size - wpabuf_len(plain) % block_size;
@@ -355,9 +418,9 @@ int wps_build_encr_settings(struct wps_data *wps, struct wpabuf *msg,
 
 	data = wpabuf_put(msg, 0);
 	wpabuf_put_buf(msg, plain);
-	wpa_printf(MSG_DEBUG,  "WPS:  * AES 128 Encrypted Settings");
 	if (aes_128_cbc_encrypt(wps->keywrapkey, iv, data, wpabuf_len(plain)))
 		return -1;
+
 	return 0;
 }
 
@@ -371,14 +434,32 @@ int wps_build_oob_dev_pw(struct wpabuf *msg, u16 dev_pw_id,
 	const u8 *addr[1];
 	u8 pubkey_hash[WPS_HASH_LEN];
 
+	wpa_printf(MSG_DEBUG, "WPS:  * OOB Device Password (dev_pw_id=%u)",
+		   dev_pw_id);
 	addr[0] = wpabuf_head(pubkey);
 	hash_len = wpabuf_len(pubkey);
-	sha256_vector(1, addr, &hash_len, pubkey_hash);
+	if (sha256_vector(1, addr, &hash_len, pubkey_hash) < 0)
+		return -1;
+#ifdef CONFIG_WPS_TESTING
+	if (wps_corrupt_pkhash) {
+		wpa_hexdump(MSG_DEBUG, "WPS: Real Public Key Hash",
+			    pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN);
+		wpa_printf(MSG_INFO, "WPS: Testing - corrupt public key hash");
+		pubkey_hash[WPS_OOB_PUBKEY_HASH_LEN - 2]++;
+	}
+#endif /* CONFIG_WPS_TESTING */
+
 	wpabuf_put_be16(msg, ATTR_OOB_DEVICE_PASSWORD);
 	wpabuf_put_be16(msg, WPS_OOB_PUBKEY_HASH_LEN + 2 + dev_pw_len);
+	wpa_hexdump(MSG_DEBUG, "WPS: Public Key Hash",
+		    pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN);
 	wpabuf_put_data(msg, pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN);
 	wpabuf_put_be16(msg, dev_pw_id);
-	wpabuf_put_data(msg, dev_pw, dev_pw_len);
+	if (dev_pw) {
+		wpa_hexdump_key(MSG_DEBUG, "WPS: OOB Device Password",
+				dev_pw, dev_pw_len);
+		wpabuf_put_data(msg, dev_pw, dev_pw_len);
+	}
 
 	return 0;
 }
@@ -415,3 +496,34 @@ struct wpabuf * wps_ie_encapsulate(struct wpabuf *data)
 
 	return ie;
 }
+
+
+int wps_build_mac_addr(struct wpabuf *msg, const u8 *addr)
+{
+	wpa_printf(MSG_DEBUG, "WPS:  * MAC Address (" MACSTR ")",
+		   MAC2STR(addr));
+	wpabuf_put_be16(msg, ATTR_MAC_ADDR);
+	wpabuf_put_be16(msg, ETH_ALEN);
+	wpabuf_put_data(msg, addr, ETH_ALEN);
+	return 0;
+}
+
+
+int wps_build_rf_bands_attr(struct wpabuf *msg, u8 rf_bands)
+{
+	wpa_printf(MSG_DEBUG, "WPS:  * RF Bands (%x)", rf_bands);
+	wpabuf_put_be16(msg, ATTR_RF_BANDS);
+	wpabuf_put_be16(msg, 1);
+	wpabuf_put_u8(msg, rf_bands);
+	return 0;
+}
+
+
+int wps_build_ap_channel(struct wpabuf *msg, u16 ap_channel)
+{
+	wpa_printf(MSG_DEBUG, "WPS:  * AP Channel (%u)", ap_channel);
+	wpabuf_put_be16(msg, ATTR_AP_CHANNEL);
+	wpabuf_put_be16(msg, 2);
+	wpabuf_put_be16(msg, ap_channel);
+	return 0;
+}

+ 131 - 96
components/wpa_supplicant/src/wps/wps_attr_parse.c

@@ -5,11 +5,12 @@
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
  */
-#include "utils/includes.h"
 
-#include "utils/common.h"
-#include "wps/wps_defs.h"
-#include "wps/wps_attr_parse.h"
+#include "includes.h"
+
+#include "common.h"
+#include "wps_defs.h"
+#include "wps_attr_parse.h"
 
 #ifndef CONFIG_WPS_STRICT
 #define WPS_WORKAROUNDS
@@ -19,12 +20,12 @@
 static int wps_set_vendor_ext_wfa_subelem(struct wps_parse_attr *attr,
 					  u8 id, u8 len, const u8 *pos)
 {
-	wpa_printf(MSG_MSGDUMP, "WPS: WFA subelement id=%u len=%u",
+	wpa_printf(MSG_EXCESSIVE, "WPS: WFA subelement id=%u len=%u",
 		   id, len);
 	switch (id) {
 	case WFA_ELEM_VERSION2:
 		if (len != 1) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid Version2 length "
+			wpa_printf(MSG_DEBUG, "WPS: Invalid Version2 length "
 				   "%u", len);
 			return -1;
 		}
@@ -36,7 +37,7 @@ static int wps_set_vendor_ext_wfa_subelem(struct wps_parse_attr *attr,
 		break;
 	case WFA_ELEM_NETWORK_KEY_SHAREABLE:
 		if (len != 1) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid Network Key "
+			wpa_printf(MSG_DEBUG, "WPS: Invalid Network Key "
 				   "Shareable length %u", len);
 			return -1;
 		}
@@ -44,7 +45,7 @@ static int wps_set_vendor_ext_wfa_subelem(struct wps_parse_attr *attr,
 		break;
 	case WFA_ELEM_REQUEST_TO_ENROLL:
 		if (len != 1) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid Request to Enroll "
+			wpa_printf(MSG_DEBUG, "WPS: Invalid Request to Enroll "
 				   "length %u", len);
 			return -1;
 		}
@@ -52,14 +53,33 @@ static int wps_set_vendor_ext_wfa_subelem(struct wps_parse_attr *attr,
 		break;
 	case WFA_ELEM_SETTINGS_DELAY_TIME:
 		if (len != 1) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid Settings Delay "
+			wpa_printf(MSG_DEBUG, "WPS: Invalid Settings Delay "
 				   "Time length %u", len);
 			return -1;
 		}
 		attr->settings_delay_time = pos;
 		break;
+	case WFA_ELEM_REGISTRAR_CONFIGURATION_METHODS:
+		if (len != 2) {
+			wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Configuration Methods length %u",
+				   len);
+			return -1;
+		}
+		attr->registrar_configuration_methods = pos;
+		break;
+	case WFA_ELEM_MULTI_AP:
+		if (len != 1) {
+			wpa_printf(MSG_DEBUG,
+				   "WPS: Invalid Multi-AP Extension length %u",
+				   len);
+			return -1;
+		}
+		attr->multi_ap_ext = *pos;
+		wpa_printf(MSG_DEBUG, "WPS: Multi-AP Extension 0x%02x",
+			   attr->multi_ap_ext);
+		break;
 	default:
-		wpa_printf(MSG_DEBUG, "WPS: Skipped unknown WFA Vendor "
+		wpa_printf(MSG_MSGDUMP, "WPS: Skipped unknown WFA Vendor "
 			   "Extension subelement %u", id);
 		break;
 	}
@@ -74,10 +94,10 @@ static int wps_parse_vendor_ext_wfa(struct wps_parse_attr *attr, const u8 *pos,
 	const u8 *end = pos + len;
 	u8 id, elen;
 
-	while (pos + 2 < end) {
+	while (end - pos >= 2) {
 		id = *pos++;
 		elen = *pos++;
-		if (pos + elen > end)
+		if (elen > end - pos)
 			break;
 		if (wps_set_vendor_ext_wfa_subelem(attr, id, elen, pos) < 0)
 			return -1;
@@ -94,7 +114,7 @@ static int wps_parse_vendor_ext(struct wps_parse_attr *attr, const u8 *pos,
 	u32 vendor_id;
 
 	if (len < 3) {
-		wpa_printf(MSG_DEBUG,  "WPS: Skip invalid Vendor Extension");
+		wpa_printf(MSG_DEBUG, "WPS: Skip invalid Vendor Extension");
 		return 0;
 	}
 
@@ -106,17 +126,17 @@ static int wps_parse_vendor_ext(struct wps_parse_attr *attr, const u8 *pos,
 
 	/* Handle unknown vendor extensions */
 
-	wpa_printf(MSG_DEBUG, "WPS: Unknown Vendor Extension (Vendor ID %u)",
+	wpa_printf(MSG_MSGDUMP, "WPS: Unknown Vendor Extension (Vendor ID %u)",
 		   vendor_id);
 
 	if (len > WPS_MAX_VENDOR_EXT_LEN) {
-		wpa_printf(MSG_DEBUG,  "WPS: Too long Vendor Extension (%u)",
+		wpa_printf(MSG_DEBUG, "WPS: Too long Vendor Extension (%u)",
 			   len);
 		return -1;
 	}
 
 	if (attr->num_vendor_ext >= MAX_WPS_PARSE_VENDOR_EXT) {
-		wpa_printf(MSG_DEBUG,  "WPS: Skipped Vendor Extension "
+		wpa_printf(MSG_DEBUG, "WPS: Skipped Vendor Extension "
 			   "attribute (max %d vendor extensions)",
 			   MAX_WPS_PARSE_VENDOR_EXT);
 		return -1;
@@ -128,13 +148,14 @@ static int wps_parse_vendor_ext(struct wps_parse_attr *attr, const u8 *pos,
 	return 0;
 }
 
+
 static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 			const u8 *pos, u16 len)
 {
 	switch (type) {
 	case ATTR_VERSION:
 		if (len != 1) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid Version length %u",
+			wpa_printf(MSG_DEBUG, "WPS: Invalid Version length %u",
 				   len);
 			return -1;
 		}
@@ -142,7 +163,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		break;
 	case ATTR_MSG_TYPE:
 		if (len != 1) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid Message Type "
+			wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type "
 				   "length %u", len);
 			return -1;
 		}
@@ -150,7 +171,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		break;
 	case ATTR_ENROLLEE_NONCE:
 		if (len != WPS_NONCE_LEN) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid Enrollee Nonce "
+			wpa_printf(MSG_DEBUG, "WPS: Invalid Enrollee Nonce "
 				   "length %u", len);
 			return -1;
 		}
@@ -158,7 +179,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		break;
 	case ATTR_REGISTRAR_NONCE:
 		if (len != WPS_NONCE_LEN) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid Registrar Nonce "
+			wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Nonce "
 				   "length %u", len);
 			return -1;
 		}
@@ -166,7 +187,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		break;
 	case ATTR_UUID_E:
 		if (len != WPS_UUID_LEN) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid UUID-E length %u",
+			wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-E length %u",
 				   len);
 			return -1;
 		}
@@ -174,7 +195,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		break;
 	case ATTR_UUID_R:
 		if (len != WPS_UUID_LEN) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid UUID-R length %u",
+			wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-R length %u",
 				   len);
 			return -1;
 		}
@@ -182,7 +203,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		break;
 	case ATTR_AUTH_TYPE_FLAGS:
 		if (len != 2) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid Authentication "
+			wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication "
 				   "Type Flags length %u", len);
 			return -1;
 		}
@@ -190,7 +211,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		break;
 	case ATTR_ENCR_TYPE_FLAGS:
 		if (len != 2) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid Encryption Type "
+			wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption Type "
 				   "Flags length %u", len);
 			return -1;
 		}
@@ -198,7 +219,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		break;
 	case ATTR_CONN_TYPE_FLAGS:
 		if (len != 1) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid Connection Type "
+			wpa_printf(MSG_DEBUG, "WPS: Invalid Connection Type "
 				   "Flags length %u", len);
 			return -1;
 		}
@@ -206,7 +227,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		break;
 	case ATTR_CONFIG_METHODS:
 		if (len != 2) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid Config Methods "
+			wpa_printf(MSG_DEBUG, "WPS: Invalid Config Methods "
 				   "length %u", len);
 			return -1;
 		}
@@ -214,7 +235,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		break;
 	case ATTR_SELECTED_REGISTRAR_CONFIG_METHODS:
 		if (len != 2) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid Selected "
+			wpa_printf(MSG_DEBUG, "WPS: Invalid Selected "
 				   "Registrar Config Methods length %u", len);
 			return -1;
 		}
@@ -222,7 +243,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		break;
 	case ATTR_PRIMARY_DEV_TYPE:
 		if (len != WPS_DEV_TYPE_LEN) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid Primary Device "
+			wpa_printf(MSG_DEBUG, "WPS: Invalid Primary Device "
 				   "Type length %u", len);
 			return -1;
 		}
@@ -230,7 +251,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		break;
 	case ATTR_RF_BANDS:
 		if (len != 1) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid RF Bands length "
+			wpa_printf(MSG_DEBUG, "WPS: Invalid RF Bands length "
 				   "%u", len);
 			return -1;
 		}
@@ -238,7 +259,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		break;
 	case ATTR_ASSOC_STATE:
 		if (len != 2) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid Association State "
+			wpa_printf(MSG_DEBUG, "WPS: Invalid Association State "
 				   "length %u", len);
 			return -1;
 		}
@@ -246,7 +267,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		break;
 	case ATTR_CONFIG_ERROR:
 		if (len != 2) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid Configuration "
+			wpa_printf(MSG_DEBUG, "WPS: Invalid Configuration "
 				   "Error length %u", len);
 			return -1;
 		}
@@ -254,18 +275,21 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		break;
 	case ATTR_DEV_PASSWORD_ID:
 		if (len != 2) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid Device Password "
+			wpa_printf(MSG_DEBUG, "WPS: Invalid Device Password "
 				   "ID length %u", len);
 			return -1;
 		}
 		attr->dev_password_id = pos;
 		break;
 	case ATTR_OOB_DEVICE_PASSWORD:
-		if (len < WPS_OOB_PUBKEY_HASH_LEN + 2 +
-		    WPS_OOB_DEVICE_PASSWORD_MIN_LEN ||
+		if (len < WPS_OOB_PUBKEY_HASH_LEN + 2 ||
 		    len > WPS_OOB_PUBKEY_HASH_LEN + 2 +
-		    WPS_OOB_DEVICE_PASSWORD_LEN) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid OOB Device "
+		    WPS_OOB_DEVICE_PASSWORD_LEN ||
+		    (len < WPS_OOB_PUBKEY_HASH_LEN + 2 +
+		     WPS_OOB_DEVICE_PASSWORD_MIN_LEN &&
+		     WPA_GET_BE16(pos + WPS_OOB_PUBKEY_HASH_LEN) !=
+		     DEV_PW_NFC_CONNECTION_HANDOVER)) {
+			wpa_printf(MSG_DEBUG, "WPS: Invalid OOB Device "
 				   "Password length %u", len);
 			return -1;
 		}
@@ -274,7 +298,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		break;
 	case ATTR_OS_VERSION:
 		if (len != 4) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid OS Version length "
+			wpa_printf(MSG_DEBUG, "WPS: Invalid OS Version length "
 				   "%u", len);
 			return -1;
 		}
@@ -282,7 +306,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		break;
 	case ATTR_WPS_STATE:
 		if (len != 1) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid Wi-Fi Protected "
+			wpa_printf(MSG_DEBUG, "WPS: Invalid Wi-Fi Protected "
 				   "Setup State length %u", len);
 			return -1;
 		}
@@ -290,7 +314,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		break;
 	case ATTR_AUTHENTICATOR:
 		if (len != WPS_AUTHENTICATOR_LEN) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid Authenticator "
+			wpa_printf(MSG_DEBUG, "WPS: Invalid Authenticator "
 				   "length %u", len);
 			return -1;
 		}
@@ -298,7 +322,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		break;
 	case ATTR_R_HASH1:
 		if (len != WPS_HASH_LEN) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid R-Hash1 length %u",
+			wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash1 length %u",
 				   len);
 			return -1;
 		}
@@ -306,7 +330,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		break;
 	case ATTR_R_HASH2:
 		if (len != WPS_HASH_LEN) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid R-Hash2 length %u",
+			wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash2 length %u",
 				   len);
 			return -1;
 		}
@@ -314,7 +338,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		break;
 	case ATTR_E_HASH1:
 		if (len != WPS_HASH_LEN) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid E-Hash1 length %u",
+			wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash1 length %u",
 				   len);
 			return -1;
 		}
@@ -322,7 +346,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		break;
 	case ATTR_E_HASH2:
 		if (len != WPS_HASH_LEN) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid E-Hash2 length %u",
+			wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash2 length %u",
 				   len);
 			return -1;
 		}
@@ -330,7 +354,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		break;
 	case ATTR_R_SNONCE1:
 		if (len != WPS_SECRET_NONCE_LEN) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid R-SNonce1 length "
+			wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce1 length "
 				   "%u", len);
 			return -1;
 		}
@@ -338,7 +362,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		break;
 	case ATTR_R_SNONCE2:
 		if (len != WPS_SECRET_NONCE_LEN) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid R-SNonce2 length "
+			wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce2 length "
 				   "%u", len);
 			return -1;
 		}
@@ -346,7 +370,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		break;
 	case ATTR_E_SNONCE1:
 		if (len != WPS_SECRET_NONCE_LEN) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid E-SNonce1 length "
+			wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce1 length "
 				   "%u", len);
 			return -1;
 		}
@@ -354,7 +378,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		break;
 	case ATTR_E_SNONCE2:
 		if (len != WPS_SECRET_NONCE_LEN) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid E-SNonce2 length "
+			wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce2 length "
 				   "%u", len);
 			return -1;
 		}
@@ -362,7 +386,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		break;
 	case ATTR_KEY_WRAP_AUTH:
 		if (len != WPS_KWA_LEN) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid Key Wrap "
+			wpa_printf(MSG_DEBUG, "WPS: Invalid Key Wrap "
 				   "Authenticator length %u", len);
 			return -1;
 		}
@@ -370,7 +394,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		break;
 	case ATTR_AUTH_TYPE:
 		if (len != 2) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid Authentication "
+			wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication "
 				   "Type length %u", len);
 			return -1;
 		}
@@ -378,7 +402,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		break;
 	case ATTR_ENCR_TYPE:
 		if (len != 2) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid Encryption "
+			wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption "
 				   "Type length %u", len);
 			return -1;
 		}
@@ -386,7 +410,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		break;
 	case ATTR_NETWORK_INDEX:
 		if (len != 1) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid Network Index "
+			wpa_printf(MSG_DEBUG, "WPS: Invalid Network Index "
 				   "length %u", len);
 			return -1;
 		}
@@ -394,7 +418,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		break;
 	case ATTR_NETWORK_KEY_INDEX:
 		if (len != 1) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid Network Key Index "
+			wpa_printf(MSG_DEBUG, "WPS: Invalid Network Key Index "
 				   "length %u", len);
 			return -1;
 		}
@@ -402,31 +426,15 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		break;
 	case ATTR_MAC_ADDR:
 		if (len != ETH_ALEN) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid MAC Address "
+			wpa_printf(MSG_DEBUG, "WPS: Invalid MAC Address "
 				   "length %u", len);
 			return -1;
 		}
 		attr->mac_addr = pos;
 		break;
-	case ATTR_KEY_PROVIDED_AUTO:
-		if (len != 1) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid Key Provided "
-				   "Automatically length %u", len);
-			return -1;
-		}
-		attr->key_prov_auto = pos;
-		break;
-	case ATTR_802_1X_ENABLED:
-		if (len != 1) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid 802.1X Enabled "
-				   "length %u", len);
-			return -1;
-		}
-		attr->dot1x_enabled = pos;
-		break;
 	case ATTR_SELECTED_REGISTRAR:
 		if (len != 1) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid Selected Registrar"
+			wpa_printf(MSG_DEBUG, "WPS: Invalid Selected Registrar"
 				   " length %u", len);
 			return -1;
 		}
@@ -434,7 +442,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		break;
 	case ATTR_REQUEST_TYPE:
 		if (len != 1) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid Request Type "
+			wpa_printf(MSG_DEBUG, "WPS: Invalid Request Type "
 				   "length %u", len);
 			return -1;
 		}
@@ -442,7 +450,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		break;
 	case ATTR_RESPONSE_TYPE:
 		if (len != 1) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid Response Type "
+			wpa_printf(MSG_DEBUG, "WPS: Invalid Response Type "
 				   "length %u", len);
 			return -1;
 		}
@@ -450,25 +458,55 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		break;
 	case ATTR_MANUFACTURER:
 		attr->manufacturer = pos;
-		attr->manufacturer_len = len;
+		if (len > WPS_MANUFACTURER_MAX_LEN)
+			attr->manufacturer_len = WPS_MANUFACTURER_MAX_LEN;
+		else
+			attr->manufacturer_len = len;
 		break;
 	case ATTR_MODEL_NAME:
 		attr->model_name = pos;
-		attr->model_name_len = len;
+		if (len > WPS_MODEL_NAME_MAX_LEN)
+			attr->model_name_len = WPS_MODEL_NAME_MAX_LEN;
+		else
+			attr->model_name_len = len;
 		break;
 	case ATTR_MODEL_NUMBER:
 		attr->model_number = pos;
-		attr->model_number_len = len;
+		if (len > WPS_MODEL_NUMBER_MAX_LEN)
+			attr->model_number_len = WPS_MODEL_NUMBER_MAX_LEN;
+		else
+			attr->model_number_len = len;
 		break;
 	case ATTR_SERIAL_NUMBER:
 		attr->serial_number = pos;
-		attr->serial_number_len = len;
+		if (len > WPS_SERIAL_NUMBER_MAX_LEN)
+			attr->serial_number_len = WPS_SERIAL_NUMBER_MAX_LEN;
+		else
+			attr->serial_number_len = len;
 		break;
 	case ATTR_DEV_NAME:
+		if (len > WPS_DEV_NAME_MAX_LEN) {
+			wpa_printf(MSG_DEBUG,
+				   "WPS: Ignore too long Device Name (len=%u)",
+				   len);
+			break;
+		}
 		attr->dev_name = pos;
 		attr->dev_name_len = len;
 		break;
 	case ATTR_PUBLIC_KEY:
+		/*
+		 * The Public Key attribute is supposed to be exactly 192 bytes
+		 * in length. Allow couple of bytes shorter one to try to
+		 * interoperate with implementations that do not use proper
+		 * zero-padding.
+		 */
+		if (len < 190 || len > 192) {
+			wpa_printf(MSG_DEBUG,
+				   "WPS: Ignore Public Key with unexpected length %u",
+				   len);
+			break;
+		}
 		attr->public_key = pos;
 		attr->public_key_len = len;
 		break;
@@ -478,7 +516,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		break;
 	case ATTR_CRED:
 		if (attr->num_cred >= MAX_CRED_COUNT) {
-			wpa_printf(MSG_DEBUG,  "WPS: Skipped Credential "
+			wpa_printf(MSG_DEBUG, "WPS: Skipped Credential "
 				   "attribute (max %d credentials)",
 				   MAX_CRED_COUNT);
 			break;
@@ -488,6 +526,11 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		attr->num_cred++;
 		break;
 	case ATTR_SSID:
+		if (len > SSID_MAX_LEN) {
+			wpa_printf(MSG_DEBUG,
+				   "WPS: Ignore too long SSID (len=%u)", len);
+			break;
+		}
 		attr->ssid = pos;
 		attr->ssid_len = len;
 		break;
@@ -495,17 +538,9 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		attr->network_key = pos;
 		attr->network_key_len = len;
 		break;
-	case ATTR_EAP_TYPE:
-		attr->eap_type = pos;
-		attr->eap_type_len = len;
-		break;
-	case ATTR_EAP_IDENTITY:
-		attr->eap_identity = pos;
-		attr->eap_identity_len = len;
-		break;
 	case ATTR_AP_SETUP_LOCKED:
 		if (len != 1) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid AP Setup Locked "
+			wpa_printf(MSG_DEBUG, "WPS: Invalid AP Setup Locked "
 				   "length %u", len);
 			return -1;
 		}
@@ -513,12 +548,12 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		break;
 	case ATTR_REQUESTED_DEV_TYPE:
 		if (len != WPS_DEV_TYPE_LEN) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid Requested Device "
+			wpa_printf(MSG_DEBUG, "WPS: Invalid Requested Device "
 				   "Type length %u", len);
 			return -1;
 		}
 		if (attr->num_req_dev_type >= MAX_REQ_DEV_TYPE_COUNT) {
-			wpa_printf(MSG_DEBUG,  "WPS: Skipped Requested Device "
+			wpa_printf(MSG_DEBUG, "WPS: Skipped Requested Device "
 				   "Type attribute (max %u types)",
 				   MAX_REQ_DEV_TYPE_COUNT);
 			break;
@@ -529,7 +564,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 	case ATTR_SECONDARY_DEV_TYPE_LIST:
 		if (len > WPS_SEC_DEV_TYPE_MAX_LEN ||
 		    (len % WPS_DEV_TYPE_LEN) > 0) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid Secondary Device "
+			wpa_printf(MSG_DEBUG, "WPS: Invalid Secondary Device "
 				   "Type length %u", len);
 			return -1;
 		}
@@ -542,14 +577,14 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
 		break;
 	case ATTR_AP_CHANNEL:
 		if (len != 2) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid AP Channel "
+			wpa_printf(MSG_DEBUG, "WPS: Invalid AP Channel "
 				   "length %u", len);
 			return -1;
 		}
 		attr->ap_channel = pos;
 		break;
 	default:
-		wpa_printf(MSG_DEBUG,  "WPS: Unsupported attribute type 0x%x "
+		wpa_printf(MSG_DEBUG, "WPS: Unsupported attribute type 0x%x "
 			   "len=%u", type, len);
 		break;
 	}
@@ -572,7 +607,7 @@ int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr)
 
 	while (pos < end) {
 		if (end - pos < 4) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid message - "
+			wpa_printf(MSG_DEBUG, "WPS: Invalid message - "
 				   "%lu bytes remaining",
 				   (unsigned long) (end - pos));
 			return -1;
@@ -582,10 +617,10 @@ int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr)
 		pos += 2;
 		len = WPA_GET_BE16(pos);
 		pos += 2;
-		wpa_printf(MSG_MSGDUMP, "WPS: attr type=0x%x len=%u",
+		wpa_printf(MSG_EXCESSIVE, "WPS: attr type=0x%x len=%u",
 			   type, len);
 		if (len > end - pos) {
-			wpa_printf(MSG_DEBUG,  "WPS: Attribute overflow");
+			wpa_printf(MSG_DEBUG, "WPS: Attribute overflow");
 			wpa_hexdump_buf(MSG_MSGDUMP, "WPS: Message data", msg);
 #ifdef WPS_WORKAROUNDS
 			/*
@@ -597,7 +632,7 @@ int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr)
 			 */
 			if ((type & 0xff00) != 0x1000 &&
 			    prev_type == ATTR_NETWORK_KEY) {
-				wpa_printf(MSG_DEBUG,  "WPS: Workaround - try "
+				wpa_printf(MSG_DEBUG, "WPS: Workaround - try "
 					   "to skip unexpected octet after "
 					   "Network Key");
 				pos -= 3;
@@ -619,7 +654,7 @@ int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr)
 					break;
 			}
 			if (i == end - pos) {
-				wpa_printf(MSG_DEBUG,  "WPS: Workaround - skip "
+				wpa_printf(MSG_DEBUG, "WPS: Workaround - skip "
 					   "unexpected message padding");
 				break;
 			}

+ 24 - 27
components/wpa_supplicant/src/wps/wps_attr_parse.h

@@ -9,7 +9,7 @@
 #ifndef WPS_ATTR_PARSE_H
 #define WPS_ATTR_PARSE_H
 
-#include "wps/wps.h"
+#include "wps.h"
 
 struct wps_parse_attr {
 	/* fixed length fields */
@@ -47,8 +47,6 @@ struct wps_parse_attr {
 	const u8 *network_idx; /* 1 octet */
 	const u8 *network_key_idx; /* 1 octet */
 	const u8 *mac_addr; /* ETH_ALEN (6) octets */
-	const u8 *key_prov_auto; /* 1 octet (Bool) */
-	const u8 *dot1x_enabled; /* 1 octet (Bool) */
 	const u8 *selected_registrar; /* 1 octet (Bool) */
 	const u8 *request_type; /* 1 octet */
 	const u8 *response_type; /* 1 octet */
@@ -57,50 +55,49 @@ struct wps_parse_attr {
 	const u8 *network_key_shareable; /* 1 octet (Bool) */
 	const u8 *request_to_enroll; /* 1 octet (Bool) */
 	const u8 *ap_channel; /* 2 octets */
+	const u8 *registrar_configuration_methods; /* 2 octets */
 
 	/* variable length fields */
 	const u8 *manufacturer;
-	size_t manufacturer_len;
 	const u8 *model_name;
-	size_t model_name_len;
 	const u8 *model_number;
-	size_t model_number_len;
 	const u8 *serial_number;
-	size_t serial_number_len;
 	const u8 *dev_name;
-	size_t dev_name_len;
 	const u8 *public_key;
-	size_t public_key_len;
 	const u8 *encr_settings;
-	size_t encr_settings_len;
 	const u8 *ssid; /* <= 32 octets */
-	size_t ssid_len;
 	const u8 *network_key; /* <= 64 octets */
-	size_t network_key_len;
-	const u8 *eap_type; /* <= 8 octets */
-	size_t eap_type_len;
-	const u8 *eap_identity; /* <= 64 octets */
-	size_t eap_identity_len;
 	const u8 *authorized_macs; /* <= 30 octets */
-	size_t authorized_macs_len;
 	const u8 *sec_dev_type_list; /* <= 128 octets */
-	size_t sec_dev_type_list_len;
 	const u8 *oob_dev_password; /* 38..54 octets */
-	size_t oob_dev_password_len;
+	u16 manufacturer_len;
+	u16 model_name_len;
+	u16 model_number_len;
+	u16 serial_number_len;
+	u16 dev_name_len;
+	u16 public_key_len;
+	u16 encr_settings_len;
+	u16 ssid_len;
+	u16 network_key_len;
+	u16 authorized_macs_len;
+	u16 sec_dev_type_list_len;
+	u16 oob_dev_password_len;
 
 	/* attributes that can occur multiple times */
 #define MAX_CRED_COUNT 10
-	const u8 *cred[MAX_CRED_COUNT];
-	size_t cred_len[MAX_CRED_COUNT];
-	size_t num_cred;
-
 #define MAX_REQ_DEV_TYPE_COUNT 10
-	const u8 *req_dev_type[MAX_REQ_DEV_TYPE_COUNT];
-	size_t num_req_dev_type;
 
+	unsigned int num_cred;
+	unsigned int num_req_dev_type;
+	unsigned int num_vendor_ext;
+
+	u16 cred_len[MAX_CRED_COUNT];
+	u16 vendor_ext_len[MAX_WPS_PARSE_VENDOR_EXT];
+
+	const u8 *cred[MAX_CRED_COUNT];
+	const u8 *req_dev_type[MAX_REQ_DEV_TYPE_COUNT];
 	const u8 *vendor_ext[MAX_WPS_PARSE_VENDOR_EXT];
-	size_t vendor_ext_len[MAX_WPS_PARSE_VENDOR_EXT];
-	size_t num_vendor_ext;
+	u8 multi_ap_ext;
 };
 
 int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr);

+ 43 - 101
components/wpa_supplicant/src/wps/wps_attr_process.c

@@ -5,11 +5,12 @@
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
  */
-#include "utils/includes.h"
 
-#include "utils/common.h"
+#include "includes.h"
+
+#include "common.h"
 #include "crypto/sha256.h"
-#include "wps/wps_i.h"
+#include "wps_i.h"
 
 
 int wps_process_authenticator(struct wps_data *wps, const u8 *authenticator,
@@ -20,13 +21,13 @@ int wps_process_authenticator(struct wps_data *wps, const u8 *authenticator,
 	size_t len[2];
 
 	if (authenticator == NULL) {
-		wpa_printf(MSG_DEBUG,  "WPS: No Authenticator attribute "
+		wpa_printf(MSG_DEBUG, "WPS: No Authenticator attribute "
 			   "included");
 		return -1;
 	}
 
 	if (wps->last_msg == NULL) {
-		wpa_printf(MSG_DEBUG,  "WPS: Last message not available for "
+		wpa_printf(MSG_DEBUG, "WPS: Last message not available for "
 			   "validating authenticator");
 		return -1;
 	}
@@ -38,9 +39,11 @@ int wps_process_authenticator(struct wps_data *wps, const u8 *authenticator,
 	len[0] = wpabuf_len(wps->last_msg);
 	addr[1] = wpabuf_head(msg);
 	len[1] = wpabuf_len(msg) - 4 - WPS_AUTHENTICATOR_LEN;
-	hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 2, addr, len, hash);
-	if (os_memcmp(hash, authenticator, WPS_AUTHENTICATOR_LEN) != 0) {
-		wpa_printf(MSG_DEBUG,  "WPS: Incorrect Authenticator");
+
+	if (hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 2, addr, len,
+			       hash) < 0 ||
+	    os_memcmp_const(hash, authenticator, WPS_AUTHENTICATOR_LEN) != 0) {
+		wpa_printf(MSG_DEBUG, "WPS: Incorrect Authenticator");
 		return -1;
 	}
 
@@ -56,21 +59,21 @@ int wps_process_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg,
 	size_t len;
 
 	if (key_wrap_auth == NULL) {
-		wpa_printf(MSG_DEBUG,  "WPS: No KWA in decrypted attribute");
+		wpa_printf(MSG_DEBUG, "WPS: No KWA in decrypted attribute");
 		return -1;
 	}
 
 	head = wpabuf_head(msg);
 	len = wpabuf_len(msg) - 4 - WPS_KWA_LEN;
 	if (head + len != key_wrap_auth - 4) {
-		wpa_printf(MSG_DEBUG,  "WPS: KWA not in the end of the "
+		wpa_printf(MSG_DEBUG, "WPS: KWA not in the end of the "
 			   "decrypted attribute");
 		return -1;
 	}
 
-	hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, head, len, hash);
-	if (os_memcmp(hash, key_wrap_auth, WPS_KWA_LEN) != 0) {
-		wpa_printf(MSG_DEBUG,  "WPS: Invalid KWA");
+	if (hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, head, len, hash) < 0 ||
+	    os_memcmp_const(hash, key_wrap_auth, WPS_KWA_LEN) != 0) {
+		wpa_printf(MSG_DEBUG, "WPS: Invalid KWA");
 		return -1;
 	}
 
@@ -82,12 +85,12 @@ static int wps_process_cred_network_idx(struct wps_credential *cred,
 					const u8 *idx)
 {
 	if (idx == NULL) {
-		wpa_printf(MSG_DEBUG,  "WPS: Credential did not include "
+		wpa_printf(MSG_DEBUG, "WPS: Credential did not include "
 			   "Network Index");
 		return -1;
 	}
 
-	wpa_printf(MSG_DEBUG,  "WPS: Network Index: %d", *idx);
+	wpa_printf(MSG_DEBUG, "WPS: Network Index: %d", *idx);
 
 	return 0;
 }
@@ -97,7 +100,7 @@ static int wps_process_cred_ssid(struct wps_credential *cred, const u8 *ssid,
 				 size_t ssid_len)
 {
 	if (ssid == NULL) {
-		wpa_printf(MSG_DEBUG,  "WPS: Credential did not include SSID");
+		wpa_printf(MSG_DEBUG, "WPS: Credential did not include SSID");
 		return -1;
 	}
 
@@ -120,13 +123,13 @@ static int wps_process_cred_auth_type(struct wps_credential *cred,
 				      const u8 *auth_type)
 {
 	if (auth_type == NULL) {
-		wpa_printf(MSG_DEBUG,  "WPS: Credential did not include "
+		wpa_printf(MSG_DEBUG, "WPS: Credential did not include "
 			   "Authentication Type");
 		return -1;
 	}
 
 	cred->auth_type = WPA_GET_BE16(auth_type);
-	wpa_printf(MSG_DEBUG,  "WPS: Authentication Type: 0x%x",
+	wpa_printf(MSG_DEBUG, "WPS: Authentication Type: 0x%x",
 		   cred->auth_type);
 
 	return 0;
@@ -137,13 +140,13 @@ static int wps_process_cred_encr_type(struct wps_credential *cred,
 				      const u8 *encr_type)
 {
 	if (encr_type == NULL) {
-		wpa_printf(MSG_DEBUG,  "WPS: Credential did not include "
+		wpa_printf(MSG_DEBUG, "WPS: Credential did not include "
 			   "Encryption Type");
 		return -1;
 	}
 
 	cred->encr_type = WPA_GET_BE16(encr_type);
-	wpa_printf(MSG_DEBUG,  "WPS: Encryption Type: 0x%x",
+	wpa_printf(MSG_DEBUG, "WPS: Encryption Type: 0x%x",
 		   cred->encr_type);
 
 	return 0;
@@ -156,7 +159,7 @@ static int wps_process_cred_network_key_idx(struct wps_credential *cred,
 	if (key_idx == NULL)
 		return 0; /* optional attribute */
 
-	wpa_printf(MSG_DEBUG,  "WPS: Network Key Index: %d", *key_idx);
+	wpa_printf(MSG_DEBUG, "WPS: Network Key Index: %d", *key_idx);
 	cred->key_idx = *key_idx;
 
 	return 0;
@@ -167,11 +170,11 @@ static int wps_process_cred_network_key(struct wps_credential *cred,
 					const u8 *key, size_t key_len)
 {
 	if (key == NULL) {
-		wpa_printf(MSG_DEBUG,  "WPS: Credential did not include "
+		wpa_printf(MSG_DEBUG, "WPS: Credential did not include "
 			   "Network Key");
-		if (cred->auth_type == WPS_WIFI_AUTH_OPEN &&
+		if (cred->auth_type == WPS_AUTH_OPEN &&
 		    cred->encr_type == WPS_ENCR_NONE) {
-			wpa_printf(MSG_DEBUG,  "WPS: Workaround - Allow "
+			wpa_printf(MSG_DEBUG, "WPS: Workaround - Allow "
 				   "missing mandatory Network Key attribute "
 				   "for open network");
 			return 0;
@@ -193,82 +196,18 @@ static int wps_process_cred_mac_addr(struct wps_credential *cred,
 				     const u8 *mac_addr)
 {
 	if (mac_addr == NULL) {
-		wpa_printf(MSG_DEBUG,  "WPS: Credential did not include "
+		wpa_printf(MSG_DEBUG, "WPS: Credential did not include "
 			   "MAC Address");
 		return -1;
 	}
 
-	wpa_printf(MSG_DEBUG,  "WPS: MAC Address " MACSTR, MAC2STR(mac_addr));
+	wpa_printf(MSG_DEBUG, "WPS: MAC Address " MACSTR, MAC2STR(mac_addr));
 	os_memcpy(cred->mac_addr, mac_addr, ETH_ALEN);
 
 	return 0;
 }
 
 
-static int wps_process_cred_eap_type(struct wps_credential *cred,
-				     const u8 *eap_type, size_t eap_type_len)
-{
-	if (eap_type == NULL)
-		return 0; /* optional attribute */
-
-	wpa_hexdump(MSG_DEBUG, "WPS: EAP Type", eap_type, eap_type_len);
-
-	return 0;
-}
-
-
-static int wps_process_cred_eap_identity(struct wps_credential *cred,
-					 const u8 *identity,
-					 size_t identity_len)
-{
-	if (identity == NULL)
-		return 0; /* optional attribute */
-
-	wpa_hexdump_ascii(MSG_DEBUG, "WPS: EAP Identity",
-			  identity, identity_len);
-
-	return 0;
-}
-
-
-static int wps_process_cred_key_prov_auto(struct wps_credential *cred,
-					  const u8 *key_prov_auto)
-{
-	if (key_prov_auto == NULL)
-		return 0; /* optional attribute */
-
-	wpa_printf(MSG_DEBUG,  "WPS: Key Provided Automatically: %d",
-		   *key_prov_auto);
-
-	return 0;
-}
-
-
-static int wps_process_cred_802_1x_enabled(struct wps_credential *cred,
-					   const u8 *dot1x_enabled)
-{
-	if (dot1x_enabled == NULL)
-		return 0; /* optional attribute */
-
-	wpa_printf(MSG_DEBUG,  "WPS: 802.1X Enabled: %d", *dot1x_enabled);
-
-	return 0;
-}
-
-
-static int wps_process_cred_ap_channel(struct wps_credential *cred,
-				       const u8 *ap_channel)
-{
-	if (ap_channel == NULL)
-		return 0; /* optional attribute */
-
-	cred->ap_channel = WPA_GET_BE16(ap_channel);
-	wpa_printf(MSG_DEBUG,  "WPS: AP Channel: %u", cred->ap_channel);
-
-	return 0;
-}
-
-
 static int wps_workaround_cred_key(struct wps_credential *cred)
 {
 	if (cred->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK) &&
@@ -286,11 +225,21 @@ static int wps_workaround_cred_key(struct wps_credential *cred)
 		 * passphrases incorrectly. Remove the extra NULL termination
 		 * to fix the encoding.
 		 */
-		wpa_printf(MSG_DEBUG,  "WPS: Workaround - remove NULL "
+		wpa_printf(MSG_DEBUG, "WPS: Workaround - remove NULL "
 			   "termination from ASCII passphrase");
 		cred->key_len--;
 #endif /* CONFIG_WPS_STRICT */
 	}
+
+
+	if (cred->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK) &&
+	    (cred->key_len < 8 || has_ctrl_char(cred->key, cred->key_len))) {
+		wpa_printf(MSG_INFO, "WPS: Reject credential with invalid WPA/WPA2-Personal passphrase");
+		wpa_hexdump_ascii_key(MSG_INFO, "WPS: Network Key",
+				      cred->key, cred->key_len);
+		return -1;
+	}
+
 	return 0;
 }
 
@@ -298,7 +247,7 @@ static int wps_workaround_cred_key(struct wps_credential *cred)
 int wps_process_cred(struct wps_parse_attr *attr,
 		     struct wps_credential *cred)
 {
-	wpa_printf(MSG_DEBUG,  "WPS: Process Credential");
+	wpa_printf(MSG_DEBUG, "WPS: Process Credential");
 
 	/* TODO: support multiple Network Keys */
 	if (wps_process_cred_network_idx(cred, attr->network_idx) ||
@@ -308,14 +257,7 @@ int wps_process_cred(struct wps_parse_attr *attr,
 	    wps_process_cred_network_key_idx(cred, attr->network_key_idx) ||
 	    wps_process_cred_network_key(cred, attr->network_key,
 					 attr->network_key_len) ||
-	    wps_process_cred_mac_addr(cred, attr->mac_addr) ||
-	    wps_process_cred_eap_type(cred, attr->eap_type,
-				      attr->eap_type_len) ||
-	    wps_process_cred_eap_identity(cred, attr->eap_identity,
-					  attr->eap_identity_len) ||
-	    wps_process_cred_key_prov_auto(cred, attr->key_prov_auto) ||
-	    wps_process_cred_802_1x_enabled(cred, attr->dot1x_enabled) ||
-	    wps_process_cred_ap_channel(cred, attr->ap_channel))
+	    wps_process_cred_mac_addr(cred, attr->mac_addr))
 		return -1;
 
 	return wps_workaround_cred_key(cred);
@@ -325,7 +267,7 @@ int wps_process_cred(struct wps_parse_attr *attr,
 int wps_process_ap_settings(struct wps_parse_attr *attr,
 			    struct wps_credential *cred)
 {
-	wpa_printf(MSG_DEBUG,  "WPS: Processing AP Settings");
+	wpa_printf(MSG_DEBUG, "WPS: Processing AP Settings");
 	os_memset(cred, 0, sizeof(*cred));
 	/* TODO: optional attributes New Password and Device Password ID */
 	if (wps_process_cred_ssid(cred, attr->ssid, attr->ssid_len) ||

+ 401 - 123
components/wpa_supplicant/src/wps/wps_common.c

@@ -5,19 +5,21 @@
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
  */
-#include <string.h>
 
-#include "utils/includes.h"
-#include "utils/common.h"
+#include "includes.h"
 
+#include "common.h"
+#include "common/defs.h"
+#include "common/ieee802_11_common.h"
 #include "crypto/aes_wrap.h"
 #include "crypto/crypto.h"
+#include "crypto/dh_group5.h"
 #include "crypto/sha1.h"
 #include "crypto/sha256.h"
-#include "crypto/dh_group5.h"
 #include "crypto/random.h"
+#include "wps_i.h"
+#include "wps_dev_attr.h"
 
-#include "wps/wps_i.h"
 
 void wps_kdf(const u8 *key, const u8 *label_prefix, size_t label_prefix_len,
 	     const char *label, u8 *res, size_t res_len)
@@ -66,13 +68,13 @@ int wps_derive_keys(struct wps_data *wps)
 	u8 keys[WPS_AUTHKEY_LEN + WPS_KEYWRAPKEY_LEN + WPS_EMSK_LEN];
 
 	if (wps->dh_privkey == NULL) {
-		wpa_printf(MSG_DEBUG,  "WPS: Own DH private key not available");
+		wpa_printf(MSG_DEBUG, "WPS: Own DH private key not available");
 		return -1;
 	}
 
 	pubkey = wps->registrar ? wps->dh_pubkey_e : wps->dh_pubkey_r;
 	if (pubkey == NULL) {
-		wpa_printf(MSG_DEBUG,  "WPS: Peer DH public key not available");
+		wpa_printf(MSG_DEBUG, "WPS: Peer DH public key not available");
 		return -1;
 	}
 
@@ -83,17 +85,17 @@ int wps_derive_keys(struct wps_data *wps)
 	wps->dh_ctx = NULL;
 	dh_shared = wpabuf_zeropad(dh_shared, 192);
 	if (dh_shared == NULL) {
-		wpa_printf(MSG_DEBUG,  "WPS: Failed to derive DH shared key");
+		wpa_printf(MSG_DEBUG, "WPS: Failed to derive DH shared key");
 		return -1;
 	}
 
 	/* Own DH private key is not needed anymore */
-/*
- * due to the public key calculated when wps start, it will not calculate anymore even when we build M1 message, also calculate the key need take a long time
- * which would cause WPS fail, so we clean the key after WPS finished .
- */
+	/*
+	 * due to the public key calculated when wps start, it will not calculate anymore even when we build M1 message, also calculate the key need take a long time
+	 * which would cause WPS fail, so we clean the key after WPS finished .
+	 */
 #ifndef ESP32_WORKAROUND
-	wpabuf_free(wps->dh_privkey);
+	wpabuf_clear_free(wps->dh_privkey);
 	wps->dh_privkey = NULL;
 #endif //ESP32_WORKAROUND
 
@@ -102,10 +104,9 @@ int wps_derive_keys(struct wps_data *wps)
 	/* DHKey = SHA-256(g^AB mod p) */
 	addr[0] = wpabuf_head(dh_shared);
 	len[0] = wpabuf_len(dh_shared);
-
 	sha256_vector(1, addr, len, dhkey);
 	wpa_hexdump_key(MSG_DEBUG, "WPS: DHKey", dhkey, sizeof(dhkey));
-	wpabuf_free(dh_shared);
+	wpabuf_clear_free(dh_shared);
 
 	/* KDK = HMAC-SHA-256_DHKey(N1 || EnrolleeMAC || N2) */
 	addr[0] = wps->nonce_e;
@@ -134,23 +135,26 @@ int wps_derive_keys(struct wps_data *wps)
 }
 
 
-void wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd,
-		    size_t dev_passwd_len)
+int wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd,
+		   size_t dev_passwd_len)
 {
 	u8 hash[SHA256_MAC_LEN];
 
-	hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, dev_passwd,
-		                             (dev_passwd_len + 1) / 2, hash);
+	if (hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, dev_passwd,
+			(dev_passwd_len + 1) / 2, hash) < 0)
+		return -1;
 	os_memcpy(wps->psk1, hash, WPS_PSK_LEN);
-	hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN,
-		            dev_passwd + (dev_passwd_len + 1) / 2,
-		            dev_passwd_len / 2, hash);
+	if (hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN,
+			dev_passwd + (dev_passwd_len + 1) / 2,
+			dev_passwd_len / 2, hash) < 0)
+		return -1;
 	os_memcpy(wps->psk2, hash, WPS_PSK_LEN);
 
 	wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: Device Password",
 			      dev_passwd, dev_passwd_len);
 	wpa_hexdump_key(MSG_DEBUG, "WPS: PSK1", wps->psk1, WPS_PSK_LEN);
 	wpa_hexdump_key(MSG_DEBUG, "WPS: PSK2", wps->psk2, WPS_PSK_LEN);
+	return 0;
 }
 
 
@@ -166,7 +170,7 @@ struct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr,
 	/* AES-128-CBC */
 	if (encr == NULL || encr_len < 2 * block_size || encr_len % block_size)
 	{
-		wpa_printf(MSG_DEBUG,  "WPS: No Encrypted Settings received");
+		wpa_printf(MSG_DEBUG, "WPS: No Encrypted Settings received");
 		return NULL;
 	}
 
@@ -176,10 +180,9 @@ struct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr,
 
 	wpa_hexdump(MSG_MSGDUMP, "WPS: Encrypted Settings", encr, encr_len);
 	wpabuf_put_data(decrypted, encr + block_size, encr_len - block_size);
-	wpa_printf(MSG_DEBUG,  "WPS: AES Decrypt setting");
 	if (aes_128_cbc_decrypt(wps->keywrapkey, encr, wpabuf_mhead(decrypted),
-				        wpabuf_len(decrypted))) {
-		wpabuf_free(decrypted);
+				wpabuf_len(decrypted))) {
+		wpabuf_clear_free(decrypted);
 		return NULL;
 	}
 
@@ -189,15 +192,15 @@ struct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr,
 	pos = wpabuf_head_u8(decrypted) + wpabuf_len(decrypted) - 1;
 	pad = *pos;
 	if (pad > wpabuf_len(decrypted)) {
-		wpa_printf(MSG_DEBUG,  "WPS: Invalid PKCS#5 v2.0 pad value");
-		wpabuf_free(decrypted);
+		wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad value");
+		wpabuf_clear_free(decrypted);
 		return NULL;
 	}
 	for (i = 0; i < pad; i++) {
 		if (*pos-- != pad) {
-			wpa_printf(MSG_DEBUG,  "WPS: Invalid PKCS#5 v2.0 pad "
+			wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad "
 				   "string");
-			wpabuf_free(decrypted);
+			wpabuf_clear_free(decrypted);
 			return NULL;
 		}
 	}
@@ -206,7 +209,7 @@ struct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr,
 	return decrypted;
 }
 
-#ifdef CONFIG_WPS_PIN
+
 /**
  * wps_pin_checksum - Compute PIN checksum
  * @pin: Seven digit PIN (i.e., eight digit PIN without the checksum digit)
@@ -241,18 +244,18 @@ unsigned int wps_pin_valid(unsigned int pin)
  * wps_generate_pin - Generate a random PIN
  * Returns: Eight digit PIN (i.e., including the checksum digit)
  */
-unsigned int wps_generate_pin(void)
+int wps_generate_pin(unsigned int *pin)
 {
 	unsigned int val;
 
 	/* Generate seven random digits for the PIN */
-	if (random_get_bytes((unsigned char *) &val, sizeof(val)) < 0) {
+	if (random_get_bytes((unsigned char *) &val, sizeof(val)) < 0)
 		return -1;
-	}
 	val %= 10000000;
 
 	/* Append checksum digit */
-	return val * 10 + wps_pin_checksum(val);
+	*pin = val * 10 + wps_pin_checksum(val);
+	return 0;
 }
 
 
@@ -270,58 +273,51 @@ int wps_pin_str_valid(const char *pin)
 	len = p - pin;
 	return len == 4 || len == 8;
 }
-#endif
+
 
 void wps_fail_event(struct wps_context *wps, enum wps_msg_type msg,
-		    u16 config_error, u16 error_indication)
+		    u16 config_error, u16 error_indication, const u8 *mac_addr)
 {
-	union wps_event_data *data;
-
-        data = (union wps_event_data *)os_zalloc(sizeof(union wps_event_data));
-	if (data == NULL)
-		return;
+	union wps_event_data data;
 
-	if (wps->event_cb == NULL) {
-		os_free(data);
+	if (wps->event_cb == NULL)
 		return;
-	}
 
-	os_memset(data, 0, sizeof(union wps_event_data));
-	data->fail.msg = msg;
-	data->fail.config_error = config_error;
-	data->fail.error_indication = error_indication;
-	wps->event_cb(wps->cb_ctx, WPS_EV_FAIL, data);
-	os_free(data);
+	os_memset(&data, 0, sizeof(data));
+	data.fail.msg = msg;
+	data.fail.config_error = config_error;
+	data.fail.error_indication = error_indication;
+	os_memcpy(data.fail.peer_macaddr, mac_addr, ETH_ALEN);
+	wps->event_cb(wps->cb_ctx, WPS_EV_FAIL, &data);
 }
 
 
-void wps_success_event(struct wps_context *wps)
+void wps_success_event(struct wps_context *wps, const u8 *mac_addr)
 {
+	union wps_event_data data;
+
 	if (wps->event_cb == NULL)
 		return;
 
-	wps->event_cb(wps->cb_ctx, WPS_EV_SUCCESS, NULL);
+	os_memset(&data, 0, sizeof(data));
+	os_memcpy(data.success.peer_macaddr, mac_addr, ETH_ALEN);
+	wps->event_cb(wps->cb_ctx, WPS_EV_SUCCESS, &data);
 }
 
 
-void wps_pwd_auth_fail_event(struct wps_context *wps, int enrollee, int part)
+void wps_pwd_auth_fail_event(struct wps_context *wps, int enrollee, int part,
+			     const u8 *mac_addr)
 {
-	union wps_event_data *data;
-
-        data = (union wps_event_data *)os_zalloc(sizeof(union wps_event_data));
-	if (data == NULL)
-		return;
+	union wps_event_data data;
 
-	if (wps->event_cb == NULL) {
-		os_free(data);
+	if (wps->event_cb == NULL)
 		return;
-	}
 
-	os_memset(data, 0, sizeof(union wps_event_data));
-	data->pwd_auth_fail.enrollee = enrollee;
-	data->pwd_auth_fail.part = part;
-	wps->event_cb(wps->cb_ctx, WPS_EV_PWD_AUTH_FAIL, data);
-	os_free(data);
+	os_memset(&data, 0, sizeof(data));
+	data.pwd_auth_fail.enrollee = enrollee;
+	data.pwd_auth_fail.part = part;
+	os_memcpy(data.pwd_auth_fail.peer_macaddr, mac_addr, ETH_ALEN);
+	wps->event_cb(wps->cb_ctx, WPS_EV_PWD_AUTH_FAIL, &data);
 }
 
 
@@ -343,38 +339,78 @@ void wps_pbc_timeout_event(struct wps_context *wps)
 }
 
 
+void wps_pbc_active_event(struct wps_context *wps)
+{
+	if (wps->event_cb == NULL)
+		return;
+
+	wps->event_cb(wps->cb_ctx, WPS_EV_PBC_ACTIVE, NULL);
+}
+
+
+void wps_pbc_disable_event(struct wps_context *wps)
+{
+	if (wps->event_cb == NULL)
+		return;
+
+	wps->event_cb(wps->cb_ctx, WPS_EV_PBC_DISABLE, NULL);
+}
+
+
 #ifdef CONFIG_WPS_OOB
 
-struct wpabuf * wps_get_oob_cred(struct wps_context *wps)
+struct wpabuf * wps_get_oob_cred(struct wps_context *wps, int rf_band,
+				 int channel)
 {
-	struct wps_data *data;
+	struct wps_data data;
 	struct wpabuf *plain;
 
-	data = (struct wps_data *)os_zalloc(sizeof(struct wps_data));
-	if (data == NULL)
-		return NULL;
-
 	plain = wpabuf_alloc(500);
 	if (plain == NULL) {
-		os_free(data);
-		wpa_printf(MSG_ERROR,  "WPS: Failed to allocate memory for OOB "
+		wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB "
 			   "credential");
 		return NULL;
 	}
 
-	os_memset(data, 0, sizeof(struct wps_data));
-	data->wps = wps;
-	data->auth_type = wps->auth_types;
-	data->encr_type = wps->encr_types;
-	if (wps_build_version(plain) ||
-	    wps_build_cred(data, plain) ||
-	    wps_build_wfa_ext(plain, 0, NULL, 0)) {
-		wpabuf_free(plain);
-		os_free(data);
+	os_memset(&data, 0, sizeof(data));
+	data.wps = wps;
+	data.auth_type = wps->auth_types;
+	data.encr_type = wps->encr_types;
+	if (wps_build_cred(&data, plain) ||
+	    (rf_band && wps_build_rf_bands_attr(plain, rf_band)) ||
+	    (channel && wps_build_ap_channel(plain, channel)) ||
+	    wps_build_mac_addr(plain, wps->dev.mac_addr) ||
+	    wps_build_wfa_ext(plain, 0, NULL, 0, 0)) {
+		os_free(data.new_psk);
+		wpabuf_clear_free(plain);
 		return NULL;
 	}
 
-	os_free(data);
+	if (wps->wps_state == WPS_STATE_NOT_CONFIGURED && data.new_psk &&
+	    wps->ap) {
+		struct wps_credential cred;
+
+		wpa_printf(MSG_DEBUG, "WPS: Moving to Configured state based "
+			   "on credential token generation");
+
+		os_memset(&cred, 0, sizeof(cred));
+		os_memcpy(cred.ssid, wps->ssid, wps->ssid_len);
+		cred.ssid_len = wps->ssid_len;
+		cred.auth_type = WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK;
+		cred.encr_type = WPS_ENCR_TKIP | WPS_ENCR_AES;
+		os_memcpy(cred.key, data.new_psk, data.new_psk_len);
+		cred.key_len = data.new_psk_len;
+
+		wps->wps_state = WPS_STATE_CONFIGURED;
+		wpa_hexdump_ascii_key(MSG_DEBUG,
+				      "WPS: Generated random passphrase",
+				      data.new_psk, data.new_psk_len);
+		if (wps->cred_cb)
+			wps->cred_cb(wps->cb_ctx, &cred);
+	}
+
+	os_free(data.new_psk);
+
 	return plain;
 }
 
@@ -390,13 +426,12 @@ struct wpabuf * wps_build_nfc_pw_token(u16 dev_pw_id,
 	if (data == NULL)
 		return NULL;
 
-	if (wps_build_version(data) ||
-	    wps_build_oob_dev_pw(data, dev_pw_id, pubkey,
+	if (wps_build_oob_dev_pw(data, dev_pw_id, pubkey,
 				 wpabuf_head(dev_pw), wpabuf_len(dev_pw)) ||
-	    wps_build_wfa_ext(data, 0, NULL, 0)) {
-		wpa_printf(MSG_ERROR,  "WPS: Failed to build NFC password "
+	    wps_build_wfa_ext(data, 0, NULL, 0, 0)) {
+		wpa_printf(MSG_ERROR, "WPS: Failed to build NFC password "
 			   "token");
-		wpabuf_free(data);
+		wpabuf_clear_free(data);
 		return NULL;
 	}
 
@@ -418,7 +453,7 @@ int wps_oob_use_cred(struct wps_context *wps, struct wps_parse_attr *attr)
 		wpabuf_set(&msg, attr->cred[i], attr->cred_len[i]);
 		if (wps_parse_msg(&msg, &cattr) < 0 ||
 		    wps_process_cred(&cattr, &local_cred)) {
-			wpa_printf(MSG_ERROR,  "WPS: Failed to parse OOB "
+			wpa_printf(MSG_ERROR, "WPS: Failed to parse OOB "
 				   "credential");
 			return -1;
 		}
@@ -438,13 +473,13 @@ int wps_dev_type_str2bin(const char *str, u8 dev_type[WPS_DEV_TYPE_LEN])
 
 	/* <categ>-<OUI>-<subcateg> */
 	WPA_PUT_BE16(dev_type, atoi(str));
-	pos = (char *)os_strchr(str, '-');
+	pos = os_strchr(str, '-');
 	if (pos == NULL)
 		return -1;
 	pos++;
 	if (hexstr2bin(pos, &dev_type[2], 4))
 		return -1;
-	pos = (char *)os_strchr(pos, '-');
+	pos = os_strchr(pos, '-');
 	if (pos == NULL)
 		return -1;
 	pos++;
@@ -460,10 +495,10 @@ char * wps_dev_type_bin2str(const u8 dev_type[WPS_DEV_TYPE_LEN], char *buf,
 {
 	int ret;
 
-	ret = snprintf(buf, buf_len, "%u-%08X-%u",
+	ret = os_snprintf(buf, buf_len, "%u-%08X-%u",
 			  WPA_GET_BE16(dev_type), WPA_GET_BE32(&dev_type[2]),
 			  WPA_GET_BE16(&dev_type[6]));
-	if (ret < 0 || (unsigned int) ret >= buf_len)
+	if (os_snprintf_error(buf_len, ret))
 		return NULL;
 
 	return buf;
@@ -502,15 +537,16 @@ u16 wps_config_methods_str2bin(const char *str)
 {
 	u16 methods = 0;
 
-	if (str == NULL) {
+	if (str == NULL || str[0] == '\0') {
 		/* Default to enabling methods based on build configuration */
 		methods |= WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD;
-#ifdef CONFIG_WPS2
 		methods |= WPS_CONFIG_VIRT_DISPLAY;
-#endif /* CONFIG_WPS2 */
 #ifdef CONFIG_WPS_NFC
 		methods |= WPS_CONFIG_NFC_INTERFACE;
 #endif /* CONFIG_WPS_NFC */
+#ifdef CONFIG_P2P
+		methods |= WPS_CONFIG_P2PS;
+#endif /* CONFIG_P2P */
 	} else {
 		if (os_strstr(str, "ethernet"))
 			methods |= WPS_CONFIG_ETHERNET;
@@ -528,7 +564,6 @@ u16 wps_config_methods_str2bin(const char *str)
 			methods |= WPS_CONFIG_PUSHBUTTON;
 		if (os_strstr(str, "keypad"))
 			methods |= WPS_CONFIG_KEYPAD;
-#ifdef CONFIG_WPS2
 		if (os_strstr(str, "virtual_display"))
 			methods |= WPS_CONFIG_VIRT_DISPLAY;
 		if (os_strstr(str, "physical_display"))
@@ -537,7 +572,8 @@ u16 wps_config_methods_str2bin(const char *str)
 			methods |= WPS_CONFIG_VIRT_PUSHBUTTON;
 		if (os_strstr(str, "physical_push_button"))
 			methods |= WPS_CONFIG_PHY_PUSHBUTTON;
-#endif /* CONFIG_WPS2 */
+		if (os_strstr(str, "p2ps"))
+			methods |= WPS_CONFIG_P2PS;
 	}
 
 	return methods;
@@ -548,7 +584,7 @@ struct wpabuf * wps_build_wsc_ack(struct wps_data *wps)
 {
 	struct wpabuf *msg;
 
-	wpa_printf(MSG_DEBUG,  "WPS: Building Message WSC_ACK");
+	wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_ACK");
 
 	msg = wpabuf_alloc(1000);
 	if (msg == NULL)
@@ -558,7 +594,7 @@ struct wpabuf * wps_build_wsc_ack(struct wps_data *wps)
 	    wps_build_msg_type(msg, WPS_WSC_ACK) ||
 	    wps_build_enrollee_nonce(wps, msg) ||
 	    wps_build_registrar_nonce(wps, msg) ||
-	    wps_build_wfa_ext(msg, 0, NULL, 0)) {
+	    wps_build_wfa_ext(msg, 0, NULL, 0, 0)) {
 		wpabuf_free(msg);
 		return NULL;
 	}
@@ -571,7 +607,7 @@ struct wpabuf * wps_build_wsc_nack(struct wps_data *wps)
 {
 	struct wpabuf *msg;
 
-	wpa_printf(MSG_DEBUG,  "WPS: Building Message WSC_NACK");
+	wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_NACK");
 
 	msg = wpabuf_alloc(1000);
 	if (msg == NULL)
@@ -582,7 +618,7 @@ struct wpabuf * wps_build_wsc_nack(struct wps_data *wps)
 	    wps_build_enrollee_nonce(wps, msg) ||
 	    wps_build_registrar_nonce(wps, msg) ||
 	    wps_build_config_error(msg, wps->config_error) ||
-	    wps_build_wfa_ext(msg, 0, NULL, 0)) {
+	    wps_build_wfa_ext(msg, 0, NULL, 0, 0)) {
 		wpabuf_free(msg);
 		return NULL;
 	}
@@ -592,12 +628,60 @@ struct wpabuf * wps_build_wsc_nack(struct wps_data *wps)
 
 
 #ifdef CONFIG_WPS_NFC
+
+struct wpabuf * wps_nfc_token_build(int ndef, int id, struct wpabuf *pubkey,
+				    struct wpabuf *dev_pw)
+{
+	struct wpabuf *ret;
+
+	if (pubkey == NULL || dev_pw == NULL)
+		return NULL;
+
+	ret = wps_build_nfc_pw_token(id, pubkey, dev_pw);
+	if (ndef && ret) {
+		struct wpabuf *tmp;
+		tmp = ndef_build_wifi(ret);
+		wpabuf_free(ret);
+		if (tmp == NULL)
+			return NULL;
+		ret = tmp;
+	}
+
+	return ret;
+}
+
+
+int wps_nfc_gen_dh(struct wpabuf **pubkey, struct wpabuf **privkey)
+{
+	struct wpabuf *priv = NULL, *pub = NULL;
+	void *dh_ctx;
+
+	dh_ctx = dh5_init(&priv, &pub);
+	if (dh_ctx == NULL)
+		return -1;
+	pub = wpabuf_zeropad(pub, 192);
+	if (pub == NULL) {
+		wpabuf_free(priv);
+		dh5_free(dh_ctx);
+		return -1;
+	}
+	wpa_hexdump_buf(MSG_DEBUG, "WPS: Generated new DH pubkey", pub);
+	dh5_free(dh_ctx);
+
+	wpabuf_free(*pubkey);
+	*pubkey = pub;
+	wpabuf_clear_free(*privkey);
+	*privkey = priv;
+
+	return 0;
+}
+
+
 struct wpabuf * wps_nfc_token_gen(int ndef, int *id, struct wpabuf **pubkey,
 				  struct wpabuf **privkey,
 				  struct wpabuf **dev_pw)
 {
-	struct wpabuf *priv = NULL, *pub = NULL, *pw, *ret;
-	void *dh_ctx;
+	struct wpabuf *pw;
 	u16 val;
 
 	pw = wpabuf_alloc(WPS_OOB_DEVICE_PASSWORD_LEN);
@@ -611,31 +695,225 @@ struct wpabuf * wps_nfc_token_gen(int ndef, int *id, struct wpabuf **pubkey,
 		return NULL;
 	}
 
-	dh_ctx = dh5_init(&priv, &pub);
-	if (dh_ctx == NULL) {
+	if (wps_nfc_gen_dh(pubkey, privkey) < 0) {
 		wpabuf_free(pw);
 		return NULL;
 	}
-	dh5_free(dh_ctx);
 
 	*id = 0x10 + val % 0xfff0;
-	wpabuf_free(*pubkey);
-	*pubkey = pub;
-	wpabuf_free(*privkey);
-	*privkey = priv;
-	wpabuf_free(*dev_pw);
+	wpabuf_clear_free(*dev_pw);
 	*dev_pw = pw;
 
-	ret = wps_build_nfc_pw_token(*id, *pubkey, *dev_pw);
-	if (ndef && ret) {
-		struct wpabuf *tmp;
-		tmp = ndef_build_wifi(ret);
-		wpabuf_free(ret);
-		if (tmp == NULL)
-			return NULL;
-		ret = tmp;
+	return wps_nfc_token_build(ndef, *id, *pubkey, *dev_pw);
+}
+
+
+struct wpabuf * wps_build_nfc_handover_req(struct wps_context *ctx,
+					   struct wpabuf *nfc_dh_pubkey)
+{
+	struct wpabuf *msg;
+	void *len;
+
+	if (ctx == NULL)
+		return NULL;
+
+	wpa_printf(MSG_DEBUG, "WPS: Building attributes for NFC connection "
+		   "handover request");
+
+	if (nfc_dh_pubkey == NULL) {
+		wpa_printf(MSG_DEBUG, "WPS: No NFC OOB Device Password "
+			   "configured");
+		return NULL;
 	}
 
-	return ret;
+	msg = wpabuf_alloc(1000);
+	if (msg == NULL)
+		return msg;
+	len = wpabuf_put(msg, 2);
+
+	if (wps_build_oob_dev_pw(msg, DEV_PW_NFC_CONNECTION_HANDOVER,
+				 nfc_dh_pubkey, NULL, 0) ||
+	    wps_build_uuid_e(msg, ctx->uuid) ||
+	    wps_build_wfa_ext(msg, 0, NULL, 0, 0)) {
+		wpabuf_free(msg);
+		return NULL;
+	}
+
+	WPA_PUT_BE16(len, wpabuf_len(msg) - 2);
+
+	return msg;
+}
+
+
+static int wps_build_ssid(struct wpabuf *msg, struct wps_context *wps)
+{
+	wpa_printf(MSG_DEBUG, "WPS:  * SSID");
+	wpa_hexdump_ascii(MSG_DEBUG, "WPS: SSID in Connection Handover Select",
+			  wps->ssid, wps->ssid_len);
+	wpabuf_put_be16(msg, ATTR_SSID);
+	wpabuf_put_be16(msg, wps->ssid_len);
+	wpabuf_put_data(msg, wps->ssid, wps->ssid_len);
+	return 0;
+}
+
+
+static int wps_build_ap_freq(struct wpabuf *msg, int freq)
+{
+	enum hostapd_hw_mode mode;
+	u8 channel, rf_band;
+	u16 ap_channel;
+
+	if (freq <= 0)
+		return 0;
+
+	mode = ieee80211_freq_to_chan(freq, &channel);
+	if (mode == NUM_HOSTAPD_MODES)
+		return 0; /* Unknown channel */
+
+	if (mode == HOSTAPD_MODE_IEEE80211G || mode == HOSTAPD_MODE_IEEE80211B)
+		rf_band = WPS_RF_24GHZ;
+	else if (mode == HOSTAPD_MODE_IEEE80211A)
+		rf_band = WPS_RF_50GHZ;
+	else if (mode == HOSTAPD_MODE_IEEE80211AD)
+		rf_band = WPS_RF_60GHZ;
+	else
+		return 0; /* Unknown band */
+	ap_channel = channel;
+
+	if (wps_build_rf_bands_attr(msg, rf_band) ||
+	    wps_build_ap_channel(msg, ap_channel))
+		return -1;
+
+	return 0;
 }
+
+
+struct wpabuf * wps_build_nfc_handover_sel(struct wps_context *ctx,
+					   struct wpabuf *nfc_dh_pubkey,
+					   const u8 *bssid, int freq)
+{
+	struct wpabuf *msg;
+	void *len;
+
+	if (ctx == NULL)
+		return NULL;
+
+	wpa_printf(MSG_DEBUG, "WPS: Building attributes for NFC connection "
+		   "handover select");
+
+	if (nfc_dh_pubkey == NULL) {
+		wpa_printf(MSG_DEBUG, "WPS: No NFC OOB Device Password "
+			   "configured");
+		return NULL;
+	}
+
+	msg = wpabuf_alloc(1000);
+	if (msg == NULL)
+		return msg;
+	len = wpabuf_put(msg, 2);
+
+	if (wps_build_oob_dev_pw(msg, DEV_PW_NFC_CONNECTION_HANDOVER,
+				 nfc_dh_pubkey, NULL, 0) ||
+	    wps_build_ssid(msg, ctx) ||
+	    wps_build_ap_freq(msg, freq) ||
+	    (bssid && wps_build_mac_addr(msg, bssid)) ||
+	    wps_build_wfa_ext(msg, 0, NULL, 0, 0)) {
+		wpabuf_free(msg);
+		return NULL;
+	}
+
+	WPA_PUT_BE16(len, wpabuf_len(msg) - 2);
+
+	return msg;
+}
+
+
+struct wpabuf * wps_build_nfc_handover_req_p2p(struct wps_context *ctx,
+					       struct wpabuf *nfc_dh_pubkey)
+{
+	struct wpabuf *msg;
+
+	if (ctx == NULL)
+		return NULL;
+
+	wpa_printf(MSG_DEBUG, "WPS: Building attributes for NFC connection "
+		   "handover request (P2P)");
+
+	if (nfc_dh_pubkey == NULL) {
+		wpa_printf(MSG_DEBUG, "WPS: No NFC DH Public Key configured");
+		return NULL;
+	}
+
+	msg = wpabuf_alloc(1000);
+	if (msg == NULL)
+		return msg;
+
+	if (wps_build_manufacturer(&ctx->dev, msg) ||
+	    wps_build_model_name(&ctx->dev, msg) ||
+	    wps_build_model_number(&ctx->dev, msg) ||
+	    wps_build_oob_dev_pw(msg, DEV_PW_NFC_CONNECTION_HANDOVER,
+				 nfc_dh_pubkey, NULL, 0) ||
+	    wps_build_rf_bands(&ctx->dev, msg, 0) ||
+	    wps_build_serial_number(&ctx->dev, msg) ||
+	    wps_build_uuid_e(msg, ctx->uuid) ||
+	    wps_build_wfa_ext(msg, 0, NULL, 0, 0)) {
+		wpabuf_free(msg);
+		return NULL;
+	}
+
+	return msg;
+}
+
+
+struct wpabuf * wps_build_nfc_handover_sel_p2p(struct wps_context *ctx,
+					       int nfc_dev_pw_id,
+					       struct wpabuf *nfc_dh_pubkey,
+					       struct wpabuf *nfc_dev_pw)
+{
+	struct wpabuf *msg;
+	const u8 *dev_pw;
+	size_t dev_pw_len;
+
+	if (ctx == NULL)
+		return NULL;
+
+	wpa_printf(MSG_DEBUG, "WPS: Building attributes for NFC connection "
+		   "handover select (P2P)");
+
+	if (nfc_dh_pubkey == NULL ||
+	    (nfc_dev_pw_id != DEV_PW_NFC_CONNECTION_HANDOVER &&
+	     nfc_dev_pw == NULL)) {
+		wpa_printf(MSG_DEBUG, "WPS: No NFC OOB Device Password "
+			   "configured");
+		return NULL;
+	}
+
+	msg = wpabuf_alloc(1000);
+	if (msg == NULL)
+		return msg;
+
+	if (nfc_dev_pw) {
+		dev_pw = wpabuf_head(nfc_dev_pw);
+		dev_pw_len = wpabuf_len(nfc_dev_pw);
+	} else {
+		dev_pw = NULL;
+		dev_pw_len = 0;
+	}
+
+	if (wps_build_manufacturer(&ctx->dev, msg) ||
+	    wps_build_model_name(&ctx->dev, msg) ||
+	    wps_build_model_number(&ctx->dev, msg) ||
+	    wps_build_oob_dev_pw(msg, nfc_dev_pw_id, nfc_dh_pubkey,
+				 dev_pw, dev_pw_len) ||
+	    wps_build_rf_bands(&ctx->dev, msg, 0) ||
+	    wps_build_serial_number(&ctx->dev, msg) ||
+	    wps_build_uuid_e(msg, ctx->uuid) ||
+	    wps_build_wfa_ext(msg, 0, NULL, 0, 0)) {
+		wpabuf_free(msg);
+		return NULL;
+	}
+
+	return msg;
+}
+
 #endif /* CONFIG_WPS_NFC */

+ 29 - 25
components/wpa_supplicant/src/wps/wps_defs.h

@@ -12,16 +12,17 @@
 #ifdef CONFIG_WPS_TESTING
 
 extern int wps_version_number;
-extern int wps_testing_dummy_cred;
+extern int wps_testing_stub_cred;
+extern int wps_corrupt_pkhash;
+extern int wps_force_auth_types_in_use;
+extern u16 wps_force_auth_types;
+extern int wps_force_encr_types_in_use;
+extern u16 wps_force_encr_types;
 #define WPS_VERSION wps_version_number
 
 #else /* CONFIG_WPS_TESTING */
 
-#ifdef CONFIG_WPS2
 #define WPS_VERSION 0x20
-#else /* CONFIG_WPS2 */
-#define WPS_VERSION 0x10
-#endif /* CONFIG_WPS2 */
 
 #endif /* CONFIG_WPS_TESTING */
 
@@ -44,6 +45,11 @@ extern int wps_testing_dummy_cred;
 #define WPS_OOB_DEVICE_PASSWORD_MIN_LEN 16
 #define WPS_OOB_DEVICE_PASSWORD_LEN 32
 #define WPS_OOB_PUBKEY_HASH_LEN 20
+#define WPS_DEV_NAME_MAX_LEN 32
+#define WPS_MANUFACTURER_MAX_LEN 64
+#define WPS_MODEL_NAME_MAX_LEN 32
+#define WPS_MODEL_NUMBER_MAX_LEN 32
+#define WPS_SERIAL_NUMBER_MAX_LEN 32
 
 /* Attribute Types */
 enum wps_attribute {
@@ -145,7 +151,9 @@ enum {
 	WFA_ELEM_AUTHORIZEDMACS = 0x01,
 	WFA_ELEM_NETWORK_KEY_SHAREABLE = 0x02,
 	WFA_ELEM_REQUEST_TO_ENROLL = 0x03,
-	WFA_ELEM_SETTINGS_DELAY_TIME = 0x04
+	WFA_ELEM_SETTINGS_DELAY_TIME = 0x04,
+	WFA_ELEM_REGISTRAR_CONFIGURATION_METHODS = 0x05,
+	WFA_ELEM_MULTI_AP = 0x06
 };
 
 /* Device Password ID */
@@ -155,13 +163,9 @@ enum wps_dev_password_id {
 	DEV_PW_MACHINE_SPECIFIED = 0x0002,
 	DEV_PW_REKEY = 0x0003,
 	DEV_PW_PUSHBUTTON = 0x0004,
-	DEV_PW_REGISTRAR_SPECIFIED = 0x0005
-};
-
-/* WPS message flag */
-enum wps_msg_flag {
-	WPS_MSG_FLAG_MORE = 0x01,
-	WPS_MSG_FLAG_LEN = 0x02
+	DEV_PW_REGISTRAR_SPECIFIED = 0x0005,
+	DEV_PW_NFC_CONNECTION_HANDOVER = 0x0007,
+	DEV_PW_P2PS_DEFAULT = 0x0008
 };
 
 /* Message Type */
@@ -184,18 +188,18 @@ enum wps_msg_type {
 };
 
 /* Authentication Type Flags */
-#define WPS_WIFI_AUTH_OPEN 0x0001
+#define WPS_AUTH_OPEN 0x0001
 #define WPS_AUTH_WPAPSK 0x0002
-#define WPS_AUTH_SHARED 0x0004
+#define WPS_AUTH_SHARED 0x0004 /* deprecated */
 #define WPS_AUTH_WPA 0x0008
 #define WPS_AUTH_WPA2 0x0010
 #define WPS_AUTH_WPA2PSK 0x0020
-#define WPS_AUTH_TYPES (WPS_WIFI_AUTH_OPEN | WPS_AUTH_WPAPSK | WPS_AUTH_SHARED | \
+#define WPS_AUTH_TYPES (WPS_AUTH_OPEN | WPS_AUTH_WPAPSK | WPS_AUTH_SHARED | \
 			WPS_AUTH_WPA | WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK)
 
 /* Encryption Type Flags */
 #define WPS_ENCR_NONE 0x0001
-#define WPS_ENCR_WEP 0x0002
+#define WPS_ENCR_WEP 0x0002 /* deprecated */
 #define WPS_ENCR_TKIP 0x0004
 #define WPS_ENCR_AES 0x0008
 #define WPS_ENCR_TYPES (WPS_ENCR_NONE | WPS_ENCR_WEP | WPS_ENCR_TKIP | \
@@ -221,7 +225,9 @@ enum wps_config_error {
 	WPS_CFG_SETUP_LOCKED = 15,
 	WPS_CFG_MSG_TIMEOUT = 16,
 	WPS_CFG_REG_SESS_TIMEOUT = 17,
-	WPS_CFG_DEV_PASSWORD_AUTH_FAILURE = 18
+	WPS_CFG_DEV_PASSWORD_AUTH_FAILURE = 18,
+	WPS_CFG_60G_CHAN_NOT_SUPPORTED = 19,
+	WPS_CFG_PUBLIC_KEY_HASH_MISMATCH = 20
 };
 
 /* Vendor specific Error Indication for WPS event messages */
@@ -229,12 +235,14 @@ enum wps_error_indication {
 	WPS_EI_NO_ERROR,
 	WPS_EI_SECURITY_TKIP_ONLY_PROHIBITED,
 	WPS_EI_SECURITY_WEP_PROHIBITED,
+	WPS_EI_AUTH_FAILURE,
 	NUM_WPS_EI_VALUES
 };
 
 /* RF Bands */
 #define WPS_RF_24GHZ 0x01
 #define WPS_RF_50GHZ 0x02
+#define WPS_RF_60GHZ 0x04
 
 /* Config Methods */
 #define WPS_CONFIG_USBA 0x0001
@@ -246,12 +254,11 @@ enum wps_error_indication {
 #define WPS_CONFIG_NFC_INTERFACE 0x0040
 #define WPS_CONFIG_PUSHBUTTON 0x0080
 #define WPS_CONFIG_KEYPAD 0x0100
-#ifdef CONFIG_WPS2
 #define WPS_CONFIG_VIRT_PUSHBUTTON 0x0280
 #define WPS_CONFIG_PHY_PUSHBUTTON 0x0480
+#define WPS_CONFIG_P2PS 0x1000
 #define WPS_CONFIG_VIRT_DISPLAY 0x2008
 #define WPS_CONFIG_PHY_DISPLAY 0x4008
-#endif /* CONFIG_WPS2 */
 
 /* Connection Type Flags */
 #define WPS_CONN_ESS 0x01
@@ -285,7 +292,8 @@ enum wps_dev_categ {
 	WPS_DEV_DISPLAY = 7,
 	WPS_DEV_MULTIMEDIA = 8,
 	WPS_DEV_GAMING = 9,
-	WPS_DEV_PHONE = 10
+	WPS_DEV_PHONE = 10,
+	WPS_DEV_AUDIO = 11,
 };
 
 enum wps_dev_subcateg {
@@ -334,8 +342,4 @@ enum wps_response_type {
 
 #define WPS_MAX_AUTHORIZED_MACS 5
 
-#define WPS_IGNORE_SEL_REG_MAX_CNT	4
-
-#define WPS_MAX_DIS_AP_NUM	10
-
 #endif /* WPS_DEFS_H */

+ 49 - 46
components/wpa_supplicant/src/wps/wps_dev_attr.c

@@ -5,11 +5,13 @@
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
  */
-#include "utils/includes.h"
-#include "utils/common.h"
 
-#include "wps/wps_i.h"
-#include "wps/wps_dev_attr.h"
+#include "includes.h"
+
+#include "common.h"
+#include "wps_i.h"
+#include "wps_dev_attr.h"
+
 
 int wps_build_manufacturer(struct wps_device_data *dev, struct wpabuf *msg)
 {
@@ -83,8 +85,7 @@ int wps_build_model_number(struct wps_device_data *dev, struct wpabuf *msg)
 }
 
 
-static int wps_build_serial_number(struct wps_device_data *dev,
-				   struct wpabuf *msg)
+int wps_build_serial_number(struct wps_device_data *dev, struct wpabuf *msg)
 {
 	size_t len;
 	wpa_printf(MSG_DEBUG,  "WPS:  * Serial Number");
@@ -215,13 +216,10 @@ int wps_build_vendor_ext_m1(struct wps_device_data *dev, struct wpabuf *msg)
 }
 
 
-int wps_build_rf_bands(struct wps_device_data *dev, struct wpabuf *msg)
+int wps_build_rf_bands(struct wps_device_data *dev, struct wpabuf *msg,
+		       u8 rf_band)
 {
-	wpa_printf(MSG_DEBUG,  "WPS:  * RF Bands (%x)", dev->rf_bands);
-	wpabuf_put_be16(msg, ATTR_RF_BANDS);
-	wpabuf_put_be16(msg, 1);
-	wpabuf_put_u8(msg, dev->rf_bands);
-	return 0;
+	return wps_build_rf_bands_attr(msg, rf_band ? rf_band : dev->rf_bands);
 }
 
 
@@ -244,6 +242,21 @@ int wps_build_vendor_ext(struct wps_device_data *dev, struct wpabuf *msg)
 }
 
 
+int wps_build_application_ext(struct wps_device_data *dev, struct wpabuf *msg)
+{
+	if (!dev->application_ext)
+		return 0;
+
+	wpa_hexdump_buf(MSG_DEBUG, "WPS:  * Application Extension",
+			dev->application_ext);
+	wpabuf_put_be16(msg, ATTR_APPLICATION_EXT);
+	wpabuf_put_be16(msg, wpabuf_len(dev->application_ext));
+	wpabuf_put_buf(msg, dev->application_ext);
+
+	return 0;
+}
+
+
 static int wps_process_manufacturer(struct wps_device_data *dev, const u8 *str,
 				    size_t str_len)
 {
@@ -255,11 +268,9 @@ static int wps_process_manufacturer(struct wps_device_data *dev, const u8 *str,
 	wpa_hexdump_ascii(MSG_DEBUG, "WPS: Manufacturer", str, str_len);
 
 	os_free(dev->manufacturer);
-	dev->manufacturer = (char *)os_malloc(str_len + 1);
+	dev->manufacturer = dup_binstr(str, str_len);
 	if (dev->manufacturer == NULL)
 		return -1;
-	os_memcpy(dev->manufacturer, str, str_len);
-	dev->manufacturer[str_len] = '\0';
 
 	return 0;
 }
@@ -276,11 +287,9 @@ static int wps_process_model_name(struct wps_device_data *dev, const u8 *str,
 	wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Name", str, str_len);
 
 	os_free(dev->model_name);
-	dev->model_name = (char *)os_malloc(str_len + 1);
+	dev->model_name = dup_binstr(str, str_len);
 	if (dev->model_name == NULL)
 		return -1;
-	os_memcpy(dev->model_name, str, str_len);
-	dev->model_name[str_len] = '\0';
 
 	return 0;
 }
@@ -297,11 +306,9 @@ static int wps_process_model_number(struct wps_device_data *dev, const u8 *str,
 	wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Number", str, str_len);
 
 	os_free(dev->model_number);
-	dev->model_number = (char *)os_malloc(str_len + 1);
+	dev->model_number = dup_binstr(str, str_len);
 	if (dev->model_number == NULL)
 		return -1;
-	os_memcpy(dev->model_number, str, str_len);
-	dev->model_number[str_len] = '\0';
 
 	return 0;
 }
@@ -318,11 +325,9 @@ static int wps_process_serial_number(struct wps_device_data *dev,
 	wpa_hexdump_ascii(MSG_DEBUG, "WPS: Serial Number", str, str_len);
 
 	os_free(dev->serial_number);
-	dev->serial_number = (char *)os_malloc(str_len + 1);
+	dev->serial_number = dup_binstr(str, str_len);
 	if (dev->serial_number == NULL)
 		return -1;
-	os_memcpy(dev->serial_number, str, str_len);
-	dev->serial_number[str_len] = '\0';
 
 	return 0;
 }
@@ -339,11 +344,9 @@ static int wps_process_dev_name(struct wps_device_data *dev, const u8 *str,
 	wpa_hexdump_ascii(MSG_DEBUG, "WPS: Device Name", str, str_len);
 
 	os_free(dev->device_name);
-	dev->device_name = (char *)os_malloc(str_len + 1);
+	dev->device_name = dup_binstr(str, str_len);
 	if (dev->device_name == NULL)
 		return -1;
-	os_memcpy(dev->device_name, str, str_len);
-	dev->device_name[str_len] = '\0';
 
 	return 0;
 }
@@ -352,12 +355,21 @@ static int wps_process_dev_name(struct wps_device_data *dev, const u8 *str,
 static int wps_process_primary_dev_type(struct wps_device_data *dev,
 					const u8 *dev_type)
 {
+#ifdef DEBUG_PRINT
+	char devtype[WPS_DEV_TYPE_BUFSIZE];
+#endif /* CONFIG_NO_STDOUT_DEBUG */
+
 	if (dev_type == NULL) {
 		wpa_printf(MSG_DEBUG,  "WPS: No Primary Device Type received");
 		return -1;
 	}
 
 	os_memcpy(dev->pri_dev_type, dev_type, WPS_DEV_TYPE_LEN);
+#ifdef DEBUG_PRINT
+	wpa_printf(MSG_DEBUG, "WPS: Primary Device Type: %s",
+		   wps_dev_type_bin2str(dev->pri_dev_type, devtype,
+					sizeof(devtype)));
+#endif
 
 	return 0;
 }
@@ -395,6 +407,14 @@ int wps_process_os_version(struct wps_device_data *dev, const u8 *ver)
 }
 
 
+void wps_process_vendor_ext_m1(struct wps_device_data *dev, const u8 ext)
+{
+	dev->multi_ap_ext = ext;
+	wpa_printf(MSG_DEBUG, "WPS: Multi-AP extension value %02x",
+		   dev->multi_ap_ext);
+}
+
+
 int wps_process_rf_bands(struct wps_device_data *dev, const u8 *bands)
 {
 	if (bands == NULL) {
@@ -409,25 +429,6 @@ int wps_process_rf_bands(struct wps_device_data *dev, const u8 *bands)
 }
 
 
-void wps_device_data_dup(struct wps_device_data *dst,
-			 const struct wps_device_data *src)
-{
-	if (src->device_name)
-		dst->device_name = os_strdup(src->device_name);
-	if (src->manufacturer)
-		dst->manufacturer = os_strdup(src->manufacturer);
-	if (src->model_name)
-		dst->model_name = os_strdup(src->model_name);
-	if (src->model_number)
-		dst->model_number = os_strdup(src->model_number);
-	if (src->serial_number)
-		dst->serial_number = os_strdup(src->serial_number);
-	os_memcpy(dst->pri_dev_type, src->pri_dev_type, WPS_DEV_TYPE_LEN);
-	dst->os_version = src->os_version;
-	dst->rf_bands = src->rf_bands;
-}
-
-
 void wps_device_data_free(struct wps_device_data *dev)
 {
 	os_free(dev->device_name);
@@ -440,4 +441,6 @@ void wps_device_data_free(struct wps_device_data *dev)
 	dev->model_number = NULL;
 	os_free(dev->serial_number);
 	dev->serial_number = NULL;
+	wpabuf_free(dev->application_ext);
+	dev->application_ext = NULL;
 }

+ 5 - 3
components/wpa_supplicant/src/wps/wps_dev_attr.h

@@ -14,11 +14,13 @@ struct wps_parse_attr;
 int wps_build_manufacturer(struct wps_device_data *dev, struct wpabuf *msg);
 int wps_build_model_name(struct wps_device_data *dev, struct wpabuf *msg);
 int wps_build_model_number(struct wps_device_data *dev, struct wpabuf *msg);
+int wps_build_serial_number(struct wps_device_data *dev, struct wpabuf *msg);
 int wps_build_dev_name(struct wps_device_data *dev, struct wpabuf *msg);
 int wps_build_device_attrs(struct wps_device_data *dev, struct wpabuf *msg);
 int wps_build_os_version(struct wps_device_data *dev, struct wpabuf *msg);
 int wps_build_vendor_ext_m1(struct wps_device_data *dev, struct wpabuf *msg);
-int wps_build_rf_bands(struct wps_device_data *dev, struct wpabuf *msg);
+int wps_build_rf_bands(struct wps_device_data *dev, struct wpabuf *msg,
+		       u8 rf_band);
 int wps_build_primary_dev_type(struct wps_device_data *dev,
 			       struct wpabuf *msg);
 int wps_build_secondary_dev_type(struct wps_device_data *dev,
@@ -27,11 +29,11 @@ int wps_build_dev_name(struct wps_device_data *dev, struct wpabuf *msg);
 int wps_process_device_attrs(struct wps_device_data *dev,
 			     struct wps_parse_attr *attr);
 int wps_process_os_version(struct wps_device_data *dev, const u8 *ver);
+void wps_process_vendor_ext_m1(struct wps_device_data *dev, const u8 ext);
 int wps_process_rf_bands(struct wps_device_data *dev, const u8 *bands);
-void wps_device_data_dup(struct wps_device_data *dst,
-			 const struct wps_device_data *src);
 void wps_device_data_free(struct wps_device_data *dev);
 int wps_build_vendor_ext(struct wps_device_data *dev, struct wpabuf *msg);
+int wps_build_application_ext(struct wps_device_data *dev, struct wpabuf *msg);
 int wps_build_req_dev_type(struct wps_device_data *dev, struct wpabuf *msg,
 			   unsigned int num_req_dev_types,
 			   const u8 *req_dev_types);

Diff do ficheiro suprimidas por serem muito extensas
+ 279 - 138
components/wpa_supplicant/src/wps/wps_enrollee.c


+ 28 - 19
components/wpa_supplicant/src/wps/wps_i.h

@@ -11,8 +11,6 @@
 
 #include "wps.h"
 #include "wps_attr_parse.h"
-#include "esp_wps.h"
-#include "esp_wifi_crypto_types.h"
 
 #ifdef CONFIG_WPS_NFC
 struct wps_nfc_pw_token;
@@ -74,6 +72,12 @@ struct wps_data {
 	size_t dev_password_len;
 	u16 dev_pw_id;
 	int pbc;
+	u8 *alt_dev_password;
+	size_t alt_dev_password_len;
+	u16 alt_dev_pw_id;
+
+	u8 peer_pubkey_hash[WPS_OOB_PUBKEY_HASH_LEN];
+	int peer_pubkey_hash_set;
 
 	/**
 	 * request_type - Request Type attribute from (Re)AssocReq
@@ -120,38 +124,36 @@ struct wps_data {
 	u8 p2p_dev_addr[ETH_ALEN]; /* P2P Device Address of the client or
 				    * 00:00:00:00:00:00 if not a P2p client */
 	int pbc_in_m1;
-#ifdef CONFIG_WPS_NFC
+
 	struct wps_nfc_pw_token *nfc_pw_token;
-#endif
+
+	int multi_ap_backhaul_sta;
 };
 
+
 /* wps_common.c */
 void wps_kdf(const u8 *key, const u8 *label_prefix, size_t label_prefix_len,
 	     const char *label, u8 *res, size_t res_len);
 int wps_derive_keys(struct wps_data *wps);
-void wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd,
-		    size_t dev_passwd_len);
+int wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd,
+		   size_t dev_passwd_len);
 struct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr,
 					  size_t encr_len);
 void wps_fail_event(struct wps_context *wps, enum wps_msg_type msg,
-		    u16 config_error, u16 error_indication);
-void wps_success_event(struct wps_context *wps);
-void wps_pwd_auth_fail_event(struct wps_context *wps, int enrollee, int part);
+		    u16 config_error, u16 error_indication, const u8 *mac_addr);
+void wps_success_event(struct wps_context *wps, const u8 *mac_addr);
+void wps_pwd_auth_fail_event(struct wps_context *wps, int enrollee, int part,
+			     const u8 *mac_addr);
 void wps_pbc_overlap_event(struct wps_context *wps);
 void wps_pbc_timeout_event(struct wps_context *wps);
+void wps_pbc_active_event(struct wps_context *wps);
+void wps_pbc_disable_event(struct wps_context *wps);
 
 struct wpabuf * wps_build_wsc_ack(struct wps_data *wps);
 struct wpabuf * wps_build_wsc_nack(struct wps_data *wps);
 
-typedef enum wps_calc_key_mode {
-	WPS_CALC_KEY_NORMAL = 0,
-	WPS_CALC_KEY_NO_CALC,
-	WPS_CALC_KEY_PRE_CALC,
-	WPS_CALC_KEY_MAX,
-} wps_key_mode_t;
-
 /* wps_attr_build.c */
-int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg, wps_key_mode_t mode);
+int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg);
 int wps_build_req_type(struct wpabuf *msg, enum wps_request_type type);
 int wps_build_resp_type(struct wpabuf *msg, enum wps_response_type type);
 int wps_build_config_methods(struct wpabuf *msg, u16 methods);
@@ -164,7 +166,8 @@ int wps_build_encr_settings(struct wps_data *wps, struct wpabuf *msg,
 			    struct wpabuf *plain);
 int wps_build_version(struct wpabuf *msg);
 int wps_build_wfa_ext(struct wpabuf *msg, int req_to_enroll,
-		      const u8 *auth_macs, size_t auth_macs_count);
+		      const u8 *auth_macs, size_t auth_macs_count,
+		      u8 multi_ap_subelem);
 int wps_build_msg_type(struct wpabuf *msg, enum wps_msg_type msg_type);
 int wps_build_enrollee_nonce(struct wps_data *wps, struct wpabuf *msg);
 int wps_build_registrar_nonce(struct wps_data *wps, struct wpabuf *msg);
@@ -176,6 +179,9 @@ int wps_build_oob_dev_pw(struct wpabuf *msg, u16 dev_pw_id,
 			 const struct wpabuf *pubkey, const u8 *dev_pw,
 			 size_t dev_pw_len);
 struct wpabuf * wps_ie_encapsulate(struct wpabuf *data);
+int wps_build_mac_addr(struct wpabuf *msg, const u8 *addr);
+int wps_build_rf_bands_attr(struct wpabuf *msg, u8 rf_bands);
+int wps_build_ap_channel(struct wpabuf *msg, u16 ap_channel);
 
 /* wps_attr_process.c */
 int wps_process_authenticator(struct wps_data *wps, const u8 *authenticator,
@@ -203,7 +209,8 @@ enum wps_process_res wps_registrar_process_msg(struct wps_data *wps,
 int wps_build_cred(struct wps_data *wps, struct wpabuf *msg);
 int wps_device_store(struct wps_registrar *reg,
 		     struct wps_device_data *dev, const u8 *uuid);
-void wps_registrar_selected_registrar_changed(struct wps_registrar *reg);
+void wps_registrar_selected_registrar_changed(struct wps_registrar *reg,
+					      u16 dev_pw_id);
 const u8 * wps_authorized_macs(struct wps_registrar *reg, size_t *count);
 int wps_registrar_pbc_overlap(struct wps_registrar *reg,
 			      const u8 *addr, const u8 *uuid_e);
@@ -212,5 +219,7 @@ int wps_registrar_pbc_overlap(struct wps_registrar *reg,
 void wps_registrar_remove_nfc_pw_token(struct wps_registrar *reg,
 				       struct wps_nfc_pw_token *token);
 #endif
+int wps_cb_new_psk(struct wps_registrar *reg, const u8 *mac_addr,
+		   const u8 *p2p_dev_addr, const u8 *psk, size_t psk_len);
 
 #endif /* WPS_I_H */

Diff do ficheiro suprimidas por serem muito extensas
+ 223 - 185
components/wpa_supplicant/src/wps/wps_registrar.c


+ 20 - 8
components/wpa_supplicant/src/wps/wps_validate.c

@@ -5,14 +5,13 @@
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
  */
+
 #include "utils/includes.h"
 
 #include "utils/common.h"
-#include "wps/wps_i.h"
-#include "wps/wps.h"
-
+#include "wps_i.h"
+#include "wps.h"
 
-#ifdef CONFIG_WPS_STRICT
 
 #ifndef WPS_STRICT_ALL
 #define WPS_STRICT_WPS2
@@ -98,11 +97,23 @@ static int wps_validate_response_type(const u8 *response_type, int mandatory)
 static int valid_config_methods(u16 val, int wps2)
 {
 	if (wps2) {
+		if ((val & 0x6000) && !(val & WPS_CONFIG_DISPLAY)) {
+			wpa_printf(MSG_INFO, "WPS-STRICT: Physical/Virtual "
+				   "Display flag without old Display flag "
+				   "set");
+			return 0;
+		}
 		if (!(val & 0x6000) && (val & WPS_CONFIG_DISPLAY)) {
 			wpa_printf(MSG_INFO, "WPS-STRICT: Display flag "
 				   "without Physical/Virtual Display flag");
 			return 0;
 		}
+		if ((val & 0x0600) && !(val & WPS_CONFIG_PUSHBUTTON)) {
+			wpa_printf(MSG_INFO, "WPS-STRICT: Physical/Virtual "
+				   "PushButton flag without old PushButton "
+				   "flag set");
+			return 0;
+		}
 		if (!(val & 0x0600) && (val & WPS_CONFIG_PUSHBUTTON)) {
 			wpa_printf(MSG_INFO, "WPS-STRICT: PushButton flag "
 				   "without Physical/Virtual PushButton flag");
@@ -213,6 +224,8 @@ static int wps_validate_rf_bands(const u8 *rf_bands, int mandatory)
 		return 0;
 	}
 	if (*rf_bands != WPS_RF_24GHZ && *rf_bands != WPS_RF_50GHZ &&
+	    *rf_bands != WPS_RF_60GHZ &&
+	    *rf_bands != (WPS_RF_24GHZ | WPS_RF_50GHZ | WPS_RF_60GHZ) &&
 	    *rf_bands != (WPS_RF_24GHZ | WPS_RF_50GHZ)) {
 		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Rf Bands "
 			   "attribute value 0x%x", *rf_bands);
@@ -256,7 +269,7 @@ static int wps_validate_config_error(const u8 *config_error, int mandatory)
 		return 0;
 	}
 	val = WPA_GET_BE16(config_error);
-	if (val > 18) {
+	if (val > 20) {
 		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Configuration Error "
 			   "attribute value 0x%04x", val);
 		return -1;
@@ -279,7 +292,7 @@ static int wps_validate_dev_password_id(const u8 *dev_password_id,
 		return 0;
 	}
 	val = WPA_GET_BE16(dev_password_id);
-	if (val >= 0x0006 && val <= 0x000f) {
+	if (val >= 0x0008 && val <= 0x000f) {
 		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Device Password ID "
 			   "attribute value 0x%04x", val);
 		return -1;
@@ -1059,7 +1072,7 @@ _out:
 }
 
 
-static int wps_validate_credential(const u8 *cred[], size_t len[], size_t num,
+static int wps_validate_credential(const u8 *cred[], u16 len[], size_t num,
 				   int mandatory)
 {
 	size_t i;
@@ -2363,4 +2376,3 @@ _out:
 
 	return ret;
 }
-#endif

+ 0 - 3
tools/ci/check_copyright_ignore.txt

@@ -1657,13 +1657,10 @@ components/wifi_provisioning/src/wifi_config.c
 components/wifi_provisioning/src/wifi_provisioning_priv.h
 components/wifi_provisioning/src/wifi_scan.c
 components/wpa_supplicant/esp_supplicant/include/esp_rrm.h
-components/wpa_supplicant/esp_supplicant/include/esp_wps.h
 components/wpa_supplicant/esp_supplicant/src/esp_scan_i.h
 components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c
 components/wpa_supplicant/esp_supplicant/src/esp_wpa3_i.h
 components/wpa_supplicant/esp_supplicant/src/esp_wpa_err.h
-components/wpa_supplicant/esp_supplicant/src/esp_wpas_glue.c
-components/wpa_supplicant/esp_supplicant/src/esp_wpas_glue.h
 components/wpa_supplicant/include/utils/wpa_debug.h
 components/wpa_supplicant/include/utils/wpabuf.h
 components/wpa_supplicant/port/include/byteswap.h

Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff