]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
WPS: Add support for NFC out-of-band mechanism
authorMasashi Honma <honma@ictec.co.jp>
Fri, 6 Mar 2009 14:16:22 +0000 (16:16 +0200)
committerJouni Malinen <j@w1.fi>
Fri, 6 Mar 2009 14:16:22 +0000 (16:16 +0200)
The new file wps_nfc.c and ndef.c implements NFC device independent
operation, wps_nfc_pn531.c implements NFC device dependent operation.

This patch is only for the following use case:
- Enrollee = wpa_supplicant
- Registrar = hostapd internal Registrar

Following NFC methods can be used:
- Enrollee PIN with NFC
- Registrar PIN with NFC
- unencrypted credential with NFC

Encrypted credentials are not supported.

Enrollee side operation:

Registrar side operation:

Example configuration.
CONFIG_WPS=y
CONFIG_WPS_NFC=y
CONFIG_WPS_NFC_PN531=y

I used NFC device "NXP PN531". The NFC device access method is
confidential, so I used outer library. Please download below files from
https://www.saice-wpsnfc.bz/index.php

[WPS NFC Library]
WpsNfcLibrary/WpsNfc.h
WpsNfcLibrary/WpsNfcType.h
WpsNfcLibrary/WpsNfcVersion.h
WpsNfcLibrary/linux/libnfc_mapping_pn53x.dll
WpsNfcLibrary/linux/wpsnfc.dll

[NFC Reader/Writer Kernel Driver]
NFCKernelDriver-1.0.3/linux/kobj/sonyrw.ko

<WiFi test>
The hostapd/wpa_supplicant with this patch passed below tests on
"Wi-Fi WPS Test Plan Version 1.6".
4.2.5 Add device using NFC Method with password token
(I used SONY STA instead of NXP STA.)

4.2.6 Add device using NFC Method with configuration token

5.1.9 Add to AP using NFC Method with password token
through internal registrar
(I used SONY AP instead of NXP AP.)

5.1.10 Add to AP using NFC Method with configuration token
through internal registrar

19 files changed:
hostapd/Makefile
hostapd/ctrl_iface.c
hostapd/hostapd_cli.c
hostapd/wps_hostapd.c
hostapd/wps_hostapd.h
src/wps/ndef.c [new file with mode: 0644]
src/wps/wps.c
src/wps/wps.h
src/wps/wps_common.c
src/wps/wps_enrollee.c
src/wps/wps_i.h
src/wps/wps_nfc.c [new file with mode: 0644]
src/wps/wps_nfc_pn531.c [new file with mode: 0644]
src/wps/wps_ufd.c
wpa_supplicant/Makefile
wpa_supplicant/ctrl_iface.c
wpa_supplicant/wpa_cli.c
wpa_supplicant/wps_supplicant.c
wpa_supplicant/wps_supplicant.h

index 0dbece698e2f694166ab0c4746b7b0d041dc579e..daa971d590720de2049de162f4d02b16dd01bcff 100644 (file)
@@ -324,6 +324,21 @@ OBJS += ../src/wps/wps_ufd.o
 NEED_WPS_OOB=y
 endif
 
+ifdef CONFIG_WPS_NFC
+CFLAGS += -DCONFIG_WPS_NFC
+OBJS += ../src/wps/ndef.o
+OBJS += ../src/wps/wps_nfc.o
+NEED_WPS_OOB=y
+ifdef CONFIG_WPS_NFC_PN531
+PN531_PATH = /usr/local/src/nfc
+CFLAGS += -DCONFIG_WPS_NFC_PN531
+CFLAGS += -I${PN531_PATH}/inc
+OBJS += ../src/wps/wps_nfc_pn531.o
+LIBS += ${PN531_PATH}/lib/wpsnfc.dll
+LIBS += ${PN531_PATH}/lib/libnfc_mapping_pn53x.dll
+endif
+endif
+
 ifdef NEED_WPS_OOB
 CFLAGS += -DCONFIG_WPS_OOB
 endif
index 5d85558faa23452793f3c5c0b4b9d7189491b785..d24c4afae6f34f2ad1a3c38ae1ac3580de36c1b3 100644 (file)
@@ -257,7 +257,7 @@ static int hostapd_ctrl_iface_wps_pin(struct hostapd_data *hapd, char *txt)
 #ifdef CONFIG_WPS_OOB
 static int hostapd_ctrl_iface_wps_oob(struct hostapd_data *hapd, char *txt)
 {
-       char *path, *method;
+       char *path, *method, *name;
 
        path = os_strchr(txt, ' ');
        if (path == NULL)
@@ -269,7 +269,11 @@ static int hostapd_ctrl_iface_wps_oob(struct hostapd_data *hapd, char *txt)
                return -1;
        *method++ = '\0';
 
-       return hostapd_wps_start_oob(hapd, txt, path, method);
+       name = os_strchr(method, ' ');
+       if (name != NULL)
+               *name++ = '\0';
+
+       return hostapd_wps_start_oob(hapd, txt, path, method, name);
 }
 #endif /* CONFIG_WPS_OOB */
 #endif /* CONFIG_WPS */
index c32d9d3ded85b14b0d9fe95a52dadee896bb1f4a..340e9c3c8b8c7c04f540b52487f0fbb32cecb814 100644 (file)
@@ -287,17 +287,24 @@ static int hostapd_cli_cmd_wps_oob(struct wpa_ctrl *ctrl, int argc,
        char cmd[256];
        int res;
 
-       if (argc != 3) {
-               printf("Invalid WPS_OOB command: need three arguments:\n"
-                      "- OOB_DEV_TYPE: use 'ufd'\n"
-                      "- OOB_PATH: path of OOB device like '/mnt'\n"
-                      "- OOB_METHOD: OOB method 'pin-e' or 'pin-r', "
-                      "'cred'\n");
+       if (argc != 3 && argc != 4) {
+               printf("Invalid WPS_OOB command: need three or four "
+                      "arguments:\n"
+                      "- DEV_TYPE: use 'ufd' or 'nfc'\n"
+                      "- PATH: path of OOB device like '/mnt'\n"
+                      "- METHOD: OOB method 'pin-e' or 'pin-r', "
+                      "'cred'\n"
+                      "- DEV_NAME: (only for NFC) device name like "
+                      "'pn531'\n");
                return -1;
        }
 
-       res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s",
-                         argv[0], argv[1], argv[2]);
+       if (argc == 3)
+               res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s",
+                                 argv[0], argv[1], argv[2]);
+       else
+               res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s %s",
+                                 argv[0], argv[1], argv[2], argv[3]);
        if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
                printf("Too long WPS_OOB command.\n");
                return -1;
index 9def50a1488cec06dfdf6d46a8f1bafcfe8c0a81..39f67ee28ca9cf4c0cd6d1ef2f1bb241e4553de8 100644 (file)
@@ -706,7 +706,7 @@ int hostapd_wps_button_pushed(struct hostapd_data *hapd)
 
 #ifdef CONFIG_WPS_OOB
 int hostapd_wps_start_oob(struct hostapd_data *hapd, char *device_type,
-                         char *path, char *method)
+                         char *path, char *method, char *name)
 {
        struct wps_context *wps = hapd->wps;
        struct oob_device_data *oob_dev;
@@ -715,6 +715,7 @@ int hostapd_wps_start_oob(struct hostapd_data *hapd, char *device_type,
        if (oob_dev == NULL)
                return -1;
        oob_dev->device_path = path;
+       oob_dev->device_name = name;
        wps->oob_conf.oob_method = wps_get_oob_method(method);
 
        if (wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_R) {
index 0d39797ffaa869e6d2b5addfceb65e12d26e9f83..9d94a4f26af5e813b688ab8d12e4113d69ff2af0 100644 (file)
@@ -24,7 +24,7 @@ int hostapd_wps_add_pin(struct hostapd_data *hapd, const char *uuid,
                        const char *pin);
 int hostapd_wps_button_pushed(struct hostapd_data *hapd);
 int hostapd_wps_start_oob(struct hostapd_data *hapd, char *device_type,
-                         char *path, char *method);
+                         char *path, char *method, char *name);
 void hostapd_wps_probe_req_rx(struct hostapd_data *hapd, const u8 *addr,
                              const u8 *ie, size_t ie_len);
 
diff --git a/src/wps/ndef.c b/src/wps/ndef.c
new file mode 100644 (file)
index 0000000..f900767
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * NDEF(NFC Data Exchange Format) routines for Wi-Fi Protected Setup
+ *   Reference is "NFCForum-TS-NDEF_1.0 2006-07-24".
+ * Copyright (c) 2009, Masashi Honma <honma@ictec.co.jp>
+ *
+ * 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.
+ */
+
+#include "includes.h"
+#include "common.h"
+#include "wps/wps.h"
+
+#define FLAG_MESSAGE_BEGIN (1 << 7)
+#define FLAG_MESSAGE_END (1 << 6)
+#define FLAG_CHUNK (1 << 5)
+#define FLAG_SHORT_RECORD (1 << 4)
+#define FLAG_ID_LENGTH_PRESENT (1 << 3)
+#define FLAG_TNF_RFC2046 (0x02)
+
+struct ndef_record {
+       u8 *type;
+       u8 *id;
+       u8 *payload;
+       u8 type_length;
+       u8 id_length;
+       u32 payload_length;
+       u32 total_length;
+};
+
+static char wifi_handover_type[] = "application/vnd.wfa.wsc";
+
+static int ndef_parse_record(u8 *data, u32 size, struct ndef_record *record)
+{
+       u8 *pos = data + 1;
+
+       if (size < 2)
+               return -1;
+       record->type_length = *pos++;
+       if (data[0] & FLAG_SHORT_RECORD) {
+               if (size < 3)
+                       return -1;
+               record->payload_length = *pos++;
+       } else {
+               if (size < 6)
+                       return -1;
+               record->payload_length = ntohl(*(u32 *)pos);
+               pos += sizeof(u32);
+       }
+
+       if (data[0] & FLAG_ID_LENGTH_PRESENT) {
+               if ((int) size < pos - data + 1)
+                       return -1;
+               record->id_length = *pos++;
+       } else
+               record->id_length = 0;
+
+       record->type = record->type_length == 0 ? NULL : pos;
+       pos += record->type_length;
+
+       record->id = record->id_length == 0 ? NULL : pos;
+       pos += record->id_length;
+
+       record->payload = record->payload_length == 0 ? NULL : pos;
+       pos += record->payload_length;
+
+       record->total_length = pos - data;
+       if (record->total_length > size)
+               return -1;
+       return 0;
+}
+
+
+static struct wpabuf * ndef_parse_records(struct wpabuf *buf,
+                                         int (*filter)(struct ndef_record *))
+{
+       struct ndef_record record;
+       int len = wpabuf_len(buf);
+       u8 *data = wpabuf_mhead(buf);
+
+       while (len > 0) {
+               if (ndef_parse_record(data, len, &record) < 0) {
+                       wpa_printf(MSG_ERROR, "NDEF : Failed to parse");
+                       return NULL;
+               }
+               if (filter == NULL || filter(&record))
+                       return wpabuf_alloc_copy(record.payload,
+                                                record.payload_length);
+               data += record.total_length;
+               len -= record.total_length;
+       }
+       wpa_printf(MSG_ERROR, "NDEF : Record not found");
+       return NULL;
+}
+
+
+static struct wpabuf * ndef_build_record(u8 flags, void *type,
+                                        u8 type_length, void *id,
+                                        u8 id_length, void *payload,
+                                        u32 payload_length)
+{
+       struct wpabuf *record;
+       size_t total_len;
+       int short_record;
+       u8 local_flag;
+
+       short_record = payload_length < 256 ? 1 : 0;
+
+       total_len = 2; /* flag + type length */
+       /* payload length */
+       total_len += short_record ? sizeof(u8) : sizeof(u32);
+       if (id_length > 0)
+               total_len += 1;
+       total_len += type_length + id_length + payload_length;
+       record = wpabuf_alloc(total_len);
+       if (record == NULL) {
+               wpa_printf(MSG_ERROR, "NDEF : Failed to allocate "
+                          "record for build");
+               return NULL;
+       }
+
+       local_flag = flags;
+       if (id_length > 0)
+               local_flag |= FLAG_ID_LENGTH_PRESENT;
+       if (short_record)
+               local_flag |= FLAG_SHORT_RECORD;
+       wpabuf_put_u8(record, local_flag);
+
+       wpabuf_put_u8(record, type_length);
+
+       if (short_record)
+               wpabuf_put_u8(record, payload_length);
+       else
+               wpabuf_put_be32(record, payload_length);
+
+       if (id_length > 0)
+               wpabuf_put_u8(record, id_length);
+       wpabuf_put_data(record, type, type_length);
+       wpabuf_put_data(record, id, id_length);
+       wpabuf_put_data(record, payload, payload_length);
+       return record;
+}
+
+
+static int wifi_filter(struct ndef_record *record)
+{
+       if (record->type_length != os_strlen(wifi_handover_type))
+               return 0;
+       if (os_memcmp(record->type, wifi_handover_type,
+                     os_strlen(wifi_handover_type)) != 0)
+               return 0;
+       return 1;
+}
+
+
+struct wpabuf * ndef_parse_wifi(struct wpabuf *buf)
+{
+       return ndef_parse_records(buf, wifi_filter);
+}
+
+
+struct wpabuf * ndef_build_wifi(struct wpabuf *buf)
+{
+       return ndef_build_record(FLAG_MESSAGE_BEGIN | FLAG_MESSAGE_END |
+                                FLAG_TNF_RFC2046, wifi_handover_type,
+                                os_strlen(wifi_handover_type), NULL, 0,
+                                wpabuf_mhead(buf), wpabuf_len(buf));
+}
index 79f3512c628b3aa91a74bfdb96d26da3e664fb63..dde16d17a5968e156b2b05a251888d204b2ae6a8 100644 (file)
@@ -305,6 +305,9 @@ struct wpabuf * wps_build_probe_req_ie(int pbc, struct wps_device_data *dev,
 #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_build_version(ie) ||
index 379033ea532e764b405eb6cf2f94184a03ee9334..70d8b0398db4dec4e38425105a0d10d59c36f652 100644 (file)
@@ -526,6 +526,7 @@ struct wps_context {
 };
 
 struct oob_device_data {
+       char *device_name;
        char *device_path;
        void * (*init_func)(struct wps_context *, struct oob_device_data *,
                            int);
@@ -534,6 +535,13 @@ struct oob_device_data {
        void (*deinit_func)(void *);
 };
 
+struct oob_nfc_device_data {
+       int (*init_func)(char *);
+       void * (*read_func)(size_t *);
+       int (*write_func)(void *, size_t);
+       void (*deinit_func)(void);
+};
+
 struct wps_registrar *
 wps_registrar_init(struct wps_context *wps,
                   const struct wps_registrar_config *cfg);
@@ -555,6 +563,7 @@ unsigned int wps_generate_pin(void);
 void wps_free_pending_msgs(struct upnp_pending_message *msgs);
 
 struct oob_device_data * wps_get_oob_device(char *device_type);
+struct oob_nfc_device_data * wps_get_oob_nfc_device(char *device_name);
 int wps_get_oob_method(char *method);
 int wps_process_oob(struct wps_context *wps, struct oob_device_data *oob_dev,
                    int registrar);
index f679ff6fe98f6a56a573ce42321e59d3b6d57ff8..65b7d99ca66664f7840178975f07da58913cc3c9 100644 (file)
@@ -525,11 +525,30 @@ struct oob_device_data * wps_get_oob_device(char *device_type)
        if (os_strstr(device_type, "ufd") != NULL)
                return &oob_ufd_device_data;
 #endif /* CONFIG_WPS_UFD */
+#ifdef CONFIG_WPS_NFC
+       if (os_strstr(device_type, "nfc") != NULL)
+               return &oob_nfc_device_data;
+#endif /* CONFIG_WPS_NFC */
 
        return NULL;
 }
 
 
+#ifdef CONFIG_WPS_NFC
+struct oob_nfc_device_data * wps_get_oob_nfc_device(char *device_name)
+{
+       if (device_name == NULL)
+               return NULL;
+#ifdef CONFIG_WPS_NFC_PN531
+       if (os_strstr(device_name, "pn531") != NULL)
+               return &oob_nfc_pn531_device_data;
+#endif /* CONFIG_WPS_NFC_PN531 */
+
+       return NULL;
+}
+#endif /* CONFIG_WPS_NFC */
+
+
 int wps_get_oob_method(char *method)
 {
        if (os_strstr(method, "pin-e") != NULL)
index 73c5ecbab92c4dccd6b1d8235ea987c67175af00..8c8d087e16b9e4faa310c3950e76a5f7d4c3d505 100644 (file)
@@ -135,6 +135,9 @@ static struct wpabuf * wps_build_m1(struct wps_data *wps)
 #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;
 
index e4c0b359ff0fa54fe640760b6a3fb6b2da3b87e1..e3cf2365495e6514e481a633b3988efc4c5e3722 100644 (file)
@@ -194,6 +194,8 @@ void wps_success_event(struct wps_context *wps);
 void wps_pwd_auth_fail_event(struct wps_context *wps, int enrollee, int part);
 
 extern struct oob_device_data oob_ufd_device_data;
+extern struct oob_device_data oob_nfc_device_data;
+extern struct oob_nfc_device_data oob_nfc_pn531_device_data;
 
 /* wps_attr_parse.c */
 int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr);
@@ -244,6 +246,9 @@ enum wps_process_res wps_registrar_process_msg(struct wps_data *wps,
                                               const struct wpabuf *msg);
 int wps_build_cred(struct wps_data *wps, struct wpabuf *msg);
 
+/* ndef.c */
+struct wpabuf * ndef_parse_wifi(struct wpabuf *buf);
+struct wpabuf * ndef_build_wifi(struct wpabuf *buf);
 
 static inline int wps_version_supported(const u8 *version)
 {
diff --git a/src/wps/wps_nfc.c b/src/wps/wps_nfc.c
new file mode 100644 (file)
index 0000000..ff12000
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * NFC routines for Wi-Fi Protected Setup
+ * Copyright (c) 2009, Masashi Honma <honma@ictec.co.jp>
+ *
+ * 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.
+ */
+
+#include "includes.h"
+#include "common.h"
+
+#include "wps/wps.h"
+#include "wps_i.h"
+
+
+struct wps_nfc_data {
+       struct oob_nfc_device_data *oob_nfc_dev;
+};
+
+
+static void * init_nfc(struct wps_context *wps,
+                      struct oob_device_data *oob_dev, int registrar)
+{
+       struct oob_nfc_device_data *oob_nfc_dev;
+       struct wps_nfc_data *data;
+
+       oob_nfc_dev = wps_get_oob_nfc_device(oob_dev->device_name);
+       if (oob_nfc_dev == NULL) {
+               wpa_printf(MSG_ERROR, "WPS (NFC): Unknown NFC device (%s)",
+                          oob_dev->device_name);
+               return NULL;
+       }
+
+       if (oob_nfc_dev->init_func(oob_dev->device_path) < 0)
+               return NULL;
+
+       data = os_zalloc(sizeof(*data));
+       if (data == NULL) {
+               wpa_printf(MSG_ERROR, "WPS (NFC): Failed to allocate "
+                          "nfc data area");
+               return NULL;
+       }
+       data->oob_nfc_dev = oob_nfc_dev;
+       return data;
+}
+
+
+static struct wpabuf * read_nfc(void *priv)
+{
+       struct wps_nfc_data *data = priv;
+       struct wpabuf *wifi, *buf;
+       char *raw_data;
+       size_t len;
+
+       raw_data = data->oob_nfc_dev->read_func(&len);
+       if (raw_data == NULL)
+               return NULL;
+
+       wifi = wpabuf_alloc_copy(raw_data, len);
+       os_free(raw_data);
+       if (wifi == NULL) {
+               wpa_printf(MSG_ERROR, "WPS (NFC): Failed to allocate "
+                          "nfc read area");
+               return NULL;
+       }
+
+       buf = ndef_parse_wifi(wifi);
+       wpabuf_free(wifi);
+       if (buf == NULL)
+               wpa_printf(MSG_ERROR, "WPS (NFC): Failed to unwrap");
+       return buf;
+}
+
+
+static int write_nfc(void *priv, struct wpabuf *buf)
+{
+       struct wps_nfc_data *data = priv;
+       struct wpabuf *wifi;
+       int ret;
+
+       wifi = ndef_build_wifi(buf);
+       if (wifi == NULL) {
+               wpa_printf(MSG_ERROR, "WPS (NFC): Failed to wrap");
+               return -1;
+       }
+
+       ret = data->oob_nfc_dev->write_func(wpabuf_mhead(wifi),
+                                           wpabuf_len(wifi));
+       wpabuf_free(wifi);
+       return ret;
+}
+
+
+static void deinit_nfc(void *priv)
+{
+       struct wps_nfc_data *data = priv;
+
+       data->oob_nfc_dev->deinit_func();
+
+       os_free(data);
+}
+
+
+struct oob_device_data oob_nfc_device_data = {
+       .device_name    = NULL,
+       .device_path    = NULL,
+       .init_func      = init_nfc,
+       .read_func      = read_nfc,
+       .write_func     = write_nfc,
+       .deinit_func    = deinit_nfc,
+};
diff --git a/src/wps/wps_nfc_pn531.c b/src/wps/wps_nfc_pn531.c
new file mode 100644 (file)
index 0000000..7e05e4d
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * NFC PN531 routines for Wi-Fi Protected Setup
+ * Copyright (c) 2009, Masashi Honma <honma@ictec.co.jp>
+ *
+ * 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.
+ */
+
+#include "includes.h"
+#include "common.h"
+
+#include "wps/wps.h"
+#include "wps_i.h"
+
+#include "WpsNfcType.h"
+#include "WpsNfc.h"
+
+
+static int init_nfc_pn531(char *path)
+{
+       u32 ret;
+
+       ret = WpsNfcInit();
+       if (ret != WPS_NFCLIB_ERR_SUCCESS) {
+               wpa_printf(MSG_ERROR, "WPS (PN531): Failed to initialize "
+                          "NFC Library: 0x%08x", ret);
+               return -1;
+       }
+
+       ret = WpsNfcOpenDevice((int8 *) path);
+       if (ret != WPS_NFCLIB_ERR_SUCCESS) {
+               wpa_printf(MSG_ERROR, "WPS (PN531): Failed to open "
+                          "NFC Device(%s): 0x%08x", path, ret);
+               goto fail;
+       }
+
+       ret = WpsNfcTokenDiscovery();
+       if (ret != WPS_NFCLIB_ERR_SUCCESS) {
+               wpa_printf(MSG_ERROR, "WPS (PN531): Failed to discover "
+                          "token: 0x%08x", ret);
+               WpsNfcCloseDevice();
+               goto fail;
+       }
+
+       return 0;
+
+fail:
+       WpsNfcDeinit();
+       return -1;
+}
+
+
+static void * read_nfc_pn531(size_t *size)
+{
+       uint32 len;
+       u32 ret;
+       int8 *data;
+
+       ret = WpsNfcRawReadToken(&data, &len);
+       if (ret != WPS_NFCLIB_ERR_SUCCESS) {
+               wpa_printf(MSG_ERROR, "WPS (PN531): Failed to read: 0x%08x",
+                          ret);
+               return NULL;
+       }
+
+       *size = len;
+       return data;
+}
+
+
+static int write_nfc_pn531(void *data, size_t len)
+{
+       u32 ret;
+
+       ret = WpsNfcRawWriteToken(data, len);
+       if (ret != WPS_NFCLIB_ERR_SUCCESS) {
+               wpa_printf(MSG_ERROR, "WPS (PN531): Failed to write: 0x%08x",
+                          ret);
+               return -1;
+       }
+
+       return 0;
+}
+
+
+static void deinit_nfc_pn531(void)
+{
+       u32 ret;
+
+       ret = WpsNfcCloseDevice();
+       if (ret != WPS_NFCLIB_ERR_SUCCESS)
+               wpa_printf(MSG_ERROR, "WPS (PN531): Failed to close "
+                          "NFC Device: 0x%08x", ret);
+
+       ret = WpsNfcDeinit();
+       if (ret != WPS_NFCLIB_ERR_SUCCESS)
+               wpa_printf(MSG_ERROR, "WPS (PN531): Failed to deinitialize "
+                          "NFC Library: 0x%08x", ret);
+}
+
+
+struct oob_nfc_device_data oob_nfc_pn531_device_data = {
+       .init_func      = init_nfc_pn531,
+       .read_func      = read_nfc_pn531,
+       .write_func     = write_nfc_pn531,
+       .deinit_func    = deinit_nfc_pn531,
+};
index 012c906ea6b406784db9592956d9d78a31fae825..0e713eeeecf3c023bc68b5e78ec20851746833de 100644 (file)
@@ -225,6 +225,7 @@ static void deinit_ufd(void *priv)
 
 
 struct oob_device_data oob_ufd_device_data = {
+       .device_name    = NULL,
        .device_path    = NULL,
        .init_func      = init_ufd,
        .read_func      = read_ufd,
index b50b661a455495ef74b57446ba5880b83cfc3684..22e4e49844253fe83ab4cb72f9c07ed92cb24540 100644 (file)
@@ -534,6 +534,21 @@ OBJS += ../src/wps/wps_ufd.o
 NEED_WPS_OOB=y
 endif
 
+ifdef CONFIG_WPS_NFC
+CFLAGS += -DCONFIG_WPS_NFC
+OBJS += ../src/wps/ndef.o
+OBJS += ../src/wps/wps_nfc.o
+NEED_WPS_OOB=y
+ifdef CONFIG_WPS_NFC_PN531
+PN531_PATH = /usr/local/src/nfc
+CFLAGS += -DCONFIG_WPS_NFC_PN531
+CFLAGS += -I${PN531_PATH}/inc
+OBJS += ../src/wps/wps_nfc_pn531.o
+LIBS += ${PN531_PATH}/lib/wpsnfc.dll
+LIBS += ${PN531_PATH}/lib/libnfc_mapping_pn53x.dll
+endif
+endif
+
 ifdef NEED_WPS_OOB
 CFLAGS += -DCONFIG_WPS_OOB
 endif
index 494672c9e8d2c24fbc63be50ce9661ad55a6c634..7aacd5230f4b185f377ff1dc859f8b1da532a2a7 100644 (file)
@@ -208,7 +208,7 @@ static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s,
 static int wpa_supplicant_ctrl_iface_wps_oob(struct wpa_supplicant *wpa_s,
                                             char *cmd)
 {
-       char *path, *method;
+       char *path, *method, *name;
 
        path = os_strchr(cmd, ' ');
        if (path == NULL)
@@ -220,7 +220,11 @@ static int wpa_supplicant_ctrl_iface_wps_oob(struct wpa_supplicant *wpa_s,
                return -1;
        *method++ = '\0';
 
-       return wpas_wps_start_oob(wpa_s, cmd, path, method);
+       name = os_strchr(method, ' ');
+       if (name != NULL)
+               *name++ = '\0';
+
+       return wpas_wps_start_oob(wpa_s, cmd, path, method, name);
 }
 #endif /* CONFIG_WPS_OOB */
 
index d6055e90bd3034886316817cc0b3730483677b37..73937d71e1899c726760246c7048ce74d8fec41f 100644 (file)
@@ -452,17 +452,24 @@ static int wpa_cli_cmd_wps_oob(struct wpa_ctrl *ctrl, int argc, char *argv[])
        char cmd[256];
        int res;
 
-       if (argc != 3) {
-               printf("Invalid WPS_OOB command: need three arguments:\n"
-                      "- OOB_DEV_TYPE: use 'ufd'\n"
-                      "- OOB_PATH: path of OOB device like '/mnt'\n"
-                      "- OOB_METHOD: OOB method 'pin-e' or 'pin-r', "
-                      "'cred'\n");
+       if (argc != 3 && argc != 4) {
+               printf("Invalid WPS_OOB command: need three or four "
+                      "arguments:\n"
+                      "- DEV_TYPE: use 'ufd' or 'nfc'\n"
+                      "- PATH: path of OOB device like '/mnt'\n"
+                      "- METHOD: OOB method 'pin-e' or 'pin-r', "
+                      "'cred'\n"
+                      "- DEV_NAME: (only for NFC) device name like "
+                      "'pn531'\n");
                return -1;
        }
 
-       res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s",
-                         argv[0], argv[1], argv[2]);
+       if (argc == 3)
+               res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s",
+                                 argv[0], argv[1], argv[2]);
+       else
+               res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s %s",
+                                 argv[0], argv[1], argv[2], argv[3]);
        if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
                printf("Too long WPS_OOB command.\n");
                return -1;
@@ -1287,7 +1294,7 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
 #ifdef CONFIG_WPS_OOB
        { "wps_oob", wpa_cli_cmd_wps_oob,
          cli_cmd_flag_sensitive,
-         "<OOB_DEV_TYPE> <OOB_PATH> <OOB_METHOD> = start WPS OOB" },
+         "<DEV_TYPE> <PATH> <METHOD> [DEV_NAME] = start WPS OOB" },
 #endif /* CONFIG_WPS_OOB */
        { "wps_reg", wpa_cli_cmd_wps_reg,
          cli_cmd_flag_sensitive,
index e6607c07f961290ce119885d2a789ad9e9093ea5..7a20284af1d9252f7fc82a09fb4071a5548836aa 100644 (file)
@@ -563,7 +563,7 @@ int wpas_wps_start_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
 
 #ifdef CONFIG_WPS_OOB
 int wpas_wps_start_oob(struct wpa_supplicant *wpa_s, char *device_type,
-                      char *path, char *method)
+                      char *path, char *method, char *name)
 {
        struct wps_context *wps = wpa_s->wps;
        struct oob_device_data *oob_dev;
@@ -572,6 +572,7 @@ int wpas_wps_start_oob(struct wpa_supplicant *wpa_s, char *device_type,
        if (oob_dev == NULL)
                return -1;
        oob_dev->device_path = path;
+       oob_dev->device_name = name;
        wps->oob_conf.oob_method = wps_get_oob_method(method);
 
        if (wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_E) {
index ad553014455fd019d2e8f791e54d2c145b3961b4..abc4b92257e741f6e4bfb7e27025a10fbb0069be 100644 (file)
@@ -28,7 +28,7 @@ int wpas_wps_start_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid);
 int wpas_wps_start_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
                       const char *pin);
 int wpas_wps_start_oob(struct wpa_supplicant *wpa_s, char *device_type,
-                      char *path, char *method);
+                      char *path, char *method, char *name);
 int wpas_wps_start_reg(struct wpa_supplicant *wpa_s, const u8 *bssid,
                       const char *pin);
 int wpas_wps_ssid_bss_match(struct wpa_supplicant *wpa_s,