Remove src/crypto from default include path
[libeap.git] / src / wps / wps_enrollee.c
index 6b6bc27..33b4420 100644 (file)
@@ -15,7 +15,8 @@
 #include "includes.h"
 
 #include "common.h"
-#include "sha256.h"
+#include "crypto/crypto.h"
+#include "crypto/sha256.h"
 #include "wps_i.h"
 #include "wps_dev_attr.h"
 
@@ -41,7 +42,7 @@ static int wps_build_wps_state(struct wps_data *wps, struct wpabuf *msg)
                   state);
        wpabuf_put_be16(msg, ATTR_WPS_STATE);
        wpabuf_put_be16(msg, 1);
-       wpabuf_put_u8(msg, WPS_STATE_NOT_CONFIGURED);
+       wpabuf_put_u8(msg, state);
        return 0;
 }
 
@@ -131,6 +132,12 @@ static struct wpabuf * wps_build_m1(struct wps_data *wps)
                return NULL;
 
        methods = WPS_CONFIG_LABEL | WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD;
+#ifdef CONFIG_WPS_UFD
+       methods |= WPS_CONFIG_USBA;
+#endif /* CONFIG_WPS_UFD */
+#ifdef CONFIG_WPS_NFC
+       methods |= WPS_CONFIG_NFC_INTERFACE;
+#endif /* CONFIG_WPS_NFC */
        if (wps->pbc)
                methods |= WPS_CONFIG_PUSHBUTTON;
 
@@ -321,6 +328,16 @@ static struct wpabuf * wps_build_m7(struct wps_data *wps)
        }
        wpabuf_free(plain);
 
+       if (wps->wps->ap && wps->wps->registrar) {
+               /*
+                * If the Registrar is only learning our current configuration,
+                * it may not continue protocol run to successful completion.
+                * Store information here to make sure it remains available.
+                */
+               wps_device_store(wps->wps->registrar, &wps->peer_dev,
+                                wps->uuid_r);
+       }
+
        wps->state = RECV_M8;
        return msg;
 }
@@ -513,6 +530,23 @@ static int wps_process_pubkey(struct wps_data *wps, const u8 *pk,
                return -1;
        }
 
+#ifdef CONFIG_WPS_OOB
+       if (wps->dev_pw_id != DEV_PW_DEFAULT &&
+           wps->wps->oob_conf.pubkey_hash) {
+               const u8 *addr[1];
+               u8 hash[WPS_HASH_LEN];
+
+               addr[0] = pk;
+               sha256_vector(1, addr, &pk_len, hash);
+               if (os_memcmp(hash,
+                             wpabuf_head(wps->wps->oob_conf.pubkey_hash),
+                             WPS_OOB_PUBKEY_HASH_LEN) != 0) {
+                       wpa_printf(MSG_ERROR, "WPS: Public Key hash error");
+                       return -1;
+               }
+       }
+#endif /* CONFIG_WPS_OOB */
+
        wpabuf_free(wps->dh_pubkey_r);
        wps->dh_pubkey_r = wpabuf_alloc_copy(pk, pk_len);
        if (wps->dh_pubkey_r == NULL)
@@ -521,10 +555,6 @@ static int wps_process_pubkey(struct wps_data *wps, const u8 *pk,
        if (wps_derive_keys(wps) < 0)
                return -1;
 
-       if (wps->request_type == WPS_REQ_WLAN_MANAGER_REGISTRAR &&
-           wps_derive_mgmt_keys(wps) < 0)
-               return -1;
-
        return 0;
 }
 
@@ -650,6 +680,21 @@ static int wps_process_cred_e(struct wps_data *wps, const u8 *cred,
            wps_process_cred(&attr, &wps->cred))
                return -1;
 
+       if (os_memcmp(wps->cred.mac_addr, wps->wps->dev.mac_addr, ETH_ALEN) !=
+           0) {
+               wpa_printf(MSG_DEBUG, "WPS: MAC Address in the Credential ("
+                          MACSTR ") does not match with own address (" MACSTR
+                          ")", MAC2STR(wps->cred.mac_addr),
+                          MAC2STR(wps->wps->dev.mac_addr));
+               /*
+                * In theory, this could be consider fatal error, but there are
+                * number of deployed implementations using other address here
+                * due to unclarity in the specification. For interoperability
+                * reasons, allow this to be processed since we do not really
+                * use the MAC Address information for anything.
+                */
+       }
+
        if (wps->wps->cred_cb) {
                wps->cred.cred_attr = cred - 4;
                wps->cred.cred_attr_len = cred_len + 4;
@@ -700,6 +745,21 @@ static int wps_process_ap_settings_e(struct wps_data *wps,
        wpa_printf(MSG_INFO, "WPS: Received new AP configuration from "
                   "Registrar");
 
+       if (os_memcmp(cred.mac_addr, wps->wps->dev.mac_addr, ETH_ALEN) !=
+           0) {
+               wpa_printf(MSG_DEBUG, "WPS: MAC Address in the AP Settings ("
+                          MACSTR ") does not match with own address (" MACSTR
+                          ")", MAC2STR(cred.mac_addr),
+                          MAC2STR(wps->wps->dev.mac_addr));
+               /*
+                * In theory, this could be consider fatal error, but there are
+                * number of deployed implementations using other address here
+                * due to unclarity in the specification. For interoperability
+                * reasons, allow this to be processed since we do not really
+                * use the MAC Address information for anything.
+                */
+       }
+
        if (wps->wps->cred_cb) {
                cred.cred_attr = wpabuf_head(attrs);
                cred.cred_attr_len = wpabuf_len(attrs);
@@ -727,7 +787,8 @@ static enum wps_process_res wps_process_m2(struct wps_data *wps,
            wps_process_enrollee_nonce(wps, attr->enrollee_nonce) ||
            wps_process_uuid_r(wps, attr->uuid_r) ||
            wps_process_pubkey(wps, attr->public_key, attr->public_key_len) ||
-           wps_process_authenticator(wps, attr->authenticator, msg)) {
+           wps_process_authenticator(wps, attr->authenticator, msg) ||
+           wps_process_device_attrs(&wps->peer_dev, attr)) {
                wps->state = SEND_WSC_NACK;
                return WPS_CONTINUE;
        }
@@ -956,7 +1017,7 @@ static enum wps_process_res wps_process_wsc_msg(struct wps_data *wps,
        if (wps_parse_msg(msg, &attr) < 0)
                return WPS_FAILURE;
 
-       if (attr.version == NULL || *attr.version != WPS_VERSION) {
+       if (!wps_version_supported(attr.version)) {
                wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x",
                           attr.version ? *attr.version : 0);
                return WPS_FAILURE;
@@ -1029,7 +1090,7 @@ static enum wps_process_res wps_process_wsc_ack(struct wps_data *wps,
        if (wps_parse_msg(msg, &attr) < 0)
                return WPS_FAILURE;
 
-       if (attr.version == NULL || *attr.version != WPS_VERSION) {
+       if (!wps_version_supported(attr.version)) {
                wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x",
                           attr.version ? *attr.version : 0);
                return WPS_FAILURE;
@@ -1081,7 +1142,7 @@ static enum wps_process_res wps_process_wsc_nack(struct wps_data *wps,
        if (wps_parse_msg(msg, &attr) < 0)
                return WPS_FAILURE;
 
-       if (attr.version == NULL || *attr.version != WPS_VERSION) {
+       if (!wps_version_supported(attr.version)) {
                wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x",
                           attr.version ? *attr.version : 0);
                return WPS_FAILURE;
@@ -1159,6 +1220,17 @@ enum wps_process_res wps_enrollee_process_msg(struct wps_data *wps,
                   "op_code=%d)",
                   (unsigned long) wpabuf_len(msg), op_code);
 
+       if (op_code == WSC_UPnP) {
+               /* Determine the OpCode based on message type attribute */
+               struct wps_parse_attr attr;
+               if (wps_parse_msg(msg, &attr) == 0 && attr.msg_type) {
+                       if (*attr.msg_type == WPS_WSC_ACK)
+                               op_code = WSC_ACK;
+                       else if (*attr.msg_type == WPS_WSC_NACK)
+                               op_code = WSC_NACK;
+               }
+       }
+
        switch (op_code) {
        case WSC_MSG:
        case WSC_UPnP: