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 0dbece6..daa971d 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 5d85558..d24c4af 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 c32d9d3..340e9c3 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 9def50a..39f67ee 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 0d39797..9d94a4f 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 79f3512..dde16d1 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 379033e..70d8b03 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 f679ff6..65b7d99 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 73c5ecb..8c8d087 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 e4c0b35..e3cf236 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 012c906..0e713ee 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 b50b661..22e4e49 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 494672c..7aacd52 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 d6055e9..73937d7 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 e6607c0..7a20284 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 ad55301..abc4b92 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,