OSDN Git Service

wpa_supplicant: Update to 07-Jul-2012 TOT
[android-x86/external-wpa_supplicant_8.git] / src / ap / wps_hostapd.c
index 8999217..07ce06c 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * hostapd / WPS integration
- * Copyright (c) 2008-2010, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2008-2012, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -12,6 +12,8 @@
 #include "utils/eloop.h"
 #include "utils/uuid.h"
 #include "crypto/dh_groups.h"
+#include "crypto/dh_group5.h"
+#include "crypto/random.h"
 #include "common/wpa_ctrl.h"
 #include "common/ieee802_11_defs.h"
 #include "common/ieee802_11_common.h"
@@ -20,6 +22,7 @@
 #include "wps/wps.h"
 #include "wps/wps_defs.h"
 #include "wps/wps_dev_attr.h"
+#include "wps/wps_attr_parse.h"
 #include "hostapd.h"
 #include "ap_config.h"
 #include "ap_drv_ops.h"
@@ -37,7 +40,8 @@ static void hostapd_wps_upnp_deinit(struct hostapd_data *hapd);
 
 static int hostapd_wps_probe_req_rx(void *ctx, const u8 *addr, const u8 *da,
                                    const u8 *bssid,
-                                   const u8 *ie, size_t ie_len);
+                                   const u8 *ie, size_t ie_len,
+                                   int ssi_signal);
 static void hostapd_wps_ap_pin_timeout(void *eloop_data, void *user_ctx);
 
 
@@ -183,19 +187,23 @@ static void hostapd_wps_pin_needed_cb(void *ctx, const u8 *uuid_e,
 struct wps_stop_reg_data {
        struct hostapd_data *current_hapd;
        const u8 *uuid_e;
+       const u8 *dev_pw;
+       size_t dev_pw_len;
 };
 
 static int wps_stop_registrar(struct hostapd_data *hapd, void *ctx)
 {
        struct wps_stop_reg_data *data = ctx;
        if (hapd != data->current_hapd && hapd->wps != NULL)
-               wps_registrar_complete(hapd->wps->registrar, data->uuid_e);
+               wps_registrar_complete(hapd->wps->registrar, data->uuid_e,
+                                      data->dev_pw, data->dev_pw_len);
        return 0;
 }
 
 
 static void hostapd_wps_reg_success_cb(void *ctx, const u8 *mac_addr,
-                                      const u8 *uuid_e)
+                                      const u8 *uuid_e, const u8 *dev_pw,
+                                      size_t dev_pw_len)
 {
        struct hostapd_data *hapd = ctx;
        char uuid[40];
@@ -209,6 +217,8 @@ static void hostapd_wps_reg_success_cb(void *ctx, const u8 *mac_addr,
                                         mac_addr, uuid_e);
        data.current_hapd = hapd;
        data.uuid_e = uuid_e;
+       data.dev_pw = dev_pw;
+       data.dev_pw_len = dev_pw_len;
        hostapd_wps_for_each(hapd, wps_stop_registrar, &data);
 }
 
@@ -984,6 +994,20 @@ int hostapd_init_wps_complete(struct hostapd_data *hapd)
 }
 
 
+static void hostapd_wps_nfc_clear(struct wps_context *wps)
+{
+#ifdef CONFIG_WPS_NFC
+       wps->ap_nfc_dev_pw_id = 0;
+       wpabuf_free(wps->ap_nfc_dh_pubkey);
+       wps->ap_nfc_dh_pubkey = NULL;
+       wpabuf_free(wps->ap_nfc_dh_privkey);
+       wps->ap_nfc_dh_privkey = NULL;
+       wpabuf_free(wps->ap_nfc_dev_pw);
+       wps->ap_nfc_dev_pw = NULL;
+#endif /* CONFIG_WPS_NFC */
+}
+
+
 void hostapd_deinit_wps(struct hostapd_data *hapd)
 {
        eloop_cancel_timeout(hostapd_wps_reenable_ap_pin, hapd, NULL);
@@ -1001,6 +1025,7 @@ void hostapd_deinit_wps(struct hostapd_data *hapd)
        wpabuf_free(hapd->wps->oob_conf.pubkey_hash);
        wpabuf_free(hapd->wps->oob_conf.dev_password);
        wps_free_pending_msgs(hapd->wps->upnp_msgs);
+       hostapd_wps_nfc_clear(hapd->wps);
        os_free(hapd->wps);
        hapd->wps = NULL;
        hostapd_wps_clear_ies(hapd);
@@ -1098,6 +1123,24 @@ int hostapd_wps_button_pushed(struct hostapd_data *hapd,
 }
 
 
+static int wps_cancel(struct hostapd_data *hapd, void *ctx)
+{
+       if (hapd->wps == NULL)
+               return 0;
+
+       wps_registrar_wps_cancel(hapd->wps->registrar);
+       ap_for_each_sta(hapd, ap_sta_wps_cancel, NULL);
+
+       return 0;
+}
+
+
+int hostapd_wps_cancel(struct hostapd_data *hapd)
+{
+       return hostapd_wps_for_each(hapd, wps_cancel, NULL);
+}
+
+
 #ifdef CONFIG_WPS_OOB
 int hostapd_wps_start_oob(struct hostapd_data *hapd, char *device_type,
                          char *path, char *method, char *name)
@@ -1154,7 +1197,8 @@ error:
 
 static int hostapd_wps_probe_req_rx(void *ctx, const u8 *addr, const u8 *da,
                                    const u8 *bssid,
-                                   const u8 *ie, size_t ie_len)
+                                   const u8 *ie, size_t ie_len,
+                                   int ssi_signal)
 {
        struct hostapd_data *hapd = ctx;
        struct wpabuf *wps_ie;
@@ -1471,3 +1515,156 @@ int hostapd_wps_config_ap(struct hostapd_data *hapd, const char *ssid,
 
        return wps_registrar_config_ap(hapd->wps->registrar, &cred);
 }
+
+
+#ifdef CONFIG_WPS_NFC
+
+struct wps_nfc_password_token_data {
+       const u8 *oob_dev_pw;
+       size_t oob_dev_pw_len;
+       int added;
+};
+
+
+static int wps_add_nfc_password_token(struct hostapd_data *hapd, void *ctx)
+{
+       struct wps_nfc_password_token_data *data = ctx;
+       int ret;
+
+       if (hapd->wps == NULL)
+               return 0;
+       ret = wps_registrar_add_nfc_password_token(hapd->wps->registrar,
+                                                  data->oob_dev_pw,
+                                                  data->oob_dev_pw_len);
+       if (ret == 0)
+               data->added++;
+       return ret;
+}
+
+
+static int hostapd_wps_add_nfc_password_token(struct hostapd_data *hapd,
+                                             struct wps_parse_attr *attr)
+{
+       struct wps_nfc_password_token_data data;
+
+       data.oob_dev_pw = attr->oob_dev_password;
+       data.oob_dev_pw_len = attr->oob_dev_password_len;
+       data.added = 0;
+       if (hostapd_wps_for_each(hapd, wps_add_nfc_password_token, &data) < 0)
+               return -1;
+       return data.added ? 0 : -1;
+}
+
+
+static int hostapd_wps_nfc_tag_process(struct hostapd_data *hapd,
+                                      const struct wpabuf *wps)
+{
+       struct wps_parse_attr attr;
+
+       wpa_hexdump_buf(MSG_DEBUG, "WPS: Received NFC tag payload", wps);
+
+       if (wps_parse_msg(wps, &attr)) {
+               wpa_printf(MSG_DEBUG, "WPS: Ignore invalid data from NFC tag");
+               return -1;
+       }
+
+       if (attr.oob_dev_password)
+               return hostapd_wps_add_nfc_password_token(hapd, &attr);
+
+       wpa_printf(MSG_DEBUG, "WPS: Ignore unrecognized NFC tag");
+       return -1;
+}
+
+
+int hostapd_wps_nfc_tag_read(struct hostapd_data *hapd,
+                            const struct wpabuf *data)
+{
+       const struct wpabuf *wps = data;
+       struct wpabuf *tmp = NULL;
+       int ret;
+
+       if (wpabuf_len(data) < 4)
+               return -1;
+
+       if (*wpabuf_head_u8(data) != 0x10) {
+               /* Assume this contains full NDEF record */
+               tmp = ndef_parse_wifi(data);
+               if (tmp == NULL) {
+                       wpa_printf(MSG_DEBUG, "WPS: Could not parse NDEF");
+                       return -1;
+               }
+               wps = tmp;
+       }
+
+       ret = hostapd_wps_nfc_tag_process(hapd, wps);
+       wpabuf_free(tmp);
+       return ret;
+}
+
+
+struct wpabuf * hostapd_wps_nfc_config_token(struct hostapd_data *hapd,
+                                            int ndef)
+{
+       struct wpabuf *ret;
+
+       if (hapd->wps == NULL)
+               return NULL;
+
+       ret = wps_get_oob_cred(hapd->wps);
+       if (ndef && ret) {
+               struct wpabuf *tmp;
+               tmp = ndef_build_wifi(ret);
+               wpabuf_free(ret);
+               if (tmp == NULL)
+                       return NULL;
+               ret = tmp;
+       }
+
+       return ret;
+}
+
+
+struct wpabuf * hostapd_wps_nfc_token_gen(struct hostapd_data *hapd, int ndef)
+{
+       return wps_nfc_token_gen(ndef, &hapd->conf->wps_nfc_dev_pw_id,
+                                &hapd->conf->wps_nfc_dh_pubkey,
+                                &hapd->conf->wps_nfc_dh_privkey,
+                                &hapd->conf->wps_nfc_dev_pw);
+}
+
+
+int hostapd_wps_nfc_token_enable(struct hostapd_data *hapd)
+{
+       struct wps_context *wps = hapd->wps;
+
+       if (wps == NULL)
+               return -1;
+
+       if (!hapd->conf->wps_nfc_dh_pubkey ||
+           !hapd->conf->wps_nfc_dh_privkey ||
+           !hapd->conf->wps_nfc_dev_pw ||
+           !hapd->conf->wps_nfc_dev_pw_id)
+               return -1;
+
+       hostapd_wps_nfc_clear(wps);
+       wps->ap_nfc_dev_pw_id = hapd->conf->wps_nfc_dev_pw_id;
+       wps->ap_nfc_dh_pubkey = wpabuf_dup(hapd->conf->wps_nfc_dh_pubkey);
+       wps->ap_nfc_dh_privkey = wpabuf_dup(hapd->conf->wps_nfc_dh_privkey);
+       wps->ap_nfc_dev_pw = wpabuf_dup(hapd->conf->wps_nfc_dev_pw);
+
+       if (!wps->ap_nfc_dh_pubkey || !wps->ap_nfc_dh_privkey ||
+           !wps->ap_nfc_dev_pw) {
+               hostapd_wps_nfc_clear(wps);
+               return -1;
+       }
+
+       return 0;
+}
+
+
+void hostapd_wps_nfc_token_disable(struct hostapd_data *hapd)
+{
+       hostapd_wps_nfc_clear(hapd->wps);
+}
+
+#endif /* CONFIG_WPS_NFC */