]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
WPS: Use separate list of NFC Password Tokens in the Registrar
authorJouni Malinen <j@w1.fi>
Wed, 27 Jun 2012 19:15:55 +0000 (22:15 +0300)
committerJouni Malinen <j@w1.fi>
Wed, 27 Jun 2012 19:15:55 +0000 (22:15 +0300)
This adds a cleaner mechanism for handling NFC Password Tokens in the
WPS Registrar. There could be more than one active NFC Password Token in
use and as such, a list of tokens needs to be maintained. The old
WPS_OOB interface is still using the old mechanism that supports only a
single active NFC Password Token.

Signed-hostap: Jouni Malinen <j@w1.fi>

src/wps/wps.c
src/wps/wps.h
src/wps/wps_i.h
src/wps/wps_registrar.c

index 64b80d808ce77580a0296a3b090cf494d0baf489..26542a067b6ca1ee288830ebeeda8f1685b8dd92 100644 (file)
@@ -118,6 +118,12 @@ struct wps_data * wps_init(const struct wps_config *cfg)
  */
 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 */
+
        if (data->wps_pin_revealed) {
                wpa_printf(MSG_DEBUG, "WPS: Full PIN information revealed and "
                           "negotiation failed");
@@ -136,6 +142,7 @@ void wps_deinit(struct wps_data *data)
        wps_device_data_free(&data->peer_dev);
        os_free(data->new_ap_settings);
        dh5_free(data->dh_ctx);
+       os_free(data->nfc_pw_token);
        os_free(data);
 }
 
index 66fccd754c13662664e66868ca6e8efa5904a471..927102f8ca13cfec39018e26a4a450966277b6d5 100644 (file)
@@ -797,6 +797,9 @@ int wps_registrar_get_info(struct wps_registrar *reg, const u8 *addr,
                           char *buf, size_t buflen);
 int wps_registrar_config_ap(struct wps_registrar *reg,
                            struct wps_credential *cred);
+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);
 int wps_registrar_add_nfc_password_token(struct wps_registrar *reg,
                                         const u8 *oob_dev_pw,
                                         size_t oob_dev_pw_len);
index a50db3f1c9cfdbff07eaf33c9c37807cd8541d9a..86ad248d374ce1d6be059631c6e55d9115e6ff96 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Wi-Fi Protected Setup - internal definitions
- * Copyright (c) 2008-2009, 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 "wps.h"
 #include "wps_attr_parse.h"
 
+struct wps_nfc_pw_token;
+
 /**
  * struct wps_data - WPS registration protocol data
  *
@@ -115,6 +117,8 @@ 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;
+
+       struct wps_nfc_pw_token *nfc_pw_token;
 };
 
 
@@ -198,5 +202,7 @@ void wps_registrar_selected_registrar_changed(struct wps_registrar *reg);
 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);
+void wps_registrar_remove_nfc_pw_token(struct wps_registrar *reg,
+                                      struct wps_nfc_pw_token *token);
 
 #endif /* WPS_I_H */
index 1bef660f6b41da82b4f19f2cbbf25993d8dc5694..154c2b4c3423861360b5fff17478da714fb35de8 100644 (file)
 #define WPS_WORKAROUNDS
 #endif /* CONFIG_WPS_STRICT */
 
+#ifdef CONFIG_WPS_NFC
+
+struct wps_nfc_pw_token {
+       struct dl_list list;
+       u8 pubkey_hash[WPS_OOB_PUBKEY_HASH_LEN];
+       u16 pw_id;
+       u8 dev_pw[WPS_OOB_DEVICE_PASSWORD_LEN];
+       size_t dev_pw_len;
+};
+
+
+static void wps_remove_nfc_pw_token(struct wps_nfc_pw_token *token)
+{
+       dl_list_del(&token->list);
+       os_free(token);
+}
+
+
+static void wps_free_nfc_pw_tokens(struct dl_list *tokens, u16 pw_id)
+{
+       struct wps_nfc_pw_token *token, *prev;
+       dl_list_for_each_safe(token, prev, tokens, struct wps_nfc_pw_token,
+                             list) {
+               if (pw_id == 0 || pw_id == token->pw_id)
+                       wps_remove_nfc_pw_token(token);
+       }
+}
+
+
+static struct wps_nfc_pw_token * wps_get_nfc_pw_token(struct dl_list *tokens,
+                                                     u16 pw_id)
+{
+       struct wps_nfc_pw_token *token;
+       dl_list_for_each(token, tokens, struct wps_nfc_pw_token, list) {
+               if (pw_id == token->pw_id)
+                       return token;
+       }
+       return NULL;
+}
+
+#else /* CONFIG_WPS_NFC */
+
+#define wps_free_nfc_pw_tokens(t, p) do { } while (0)
+
+#endif /* CONFIG_WPS_NFC */
+
+
 struct wps_uuid_pin {
        struct dl_list list;
        u8 uuid[WPS_UUID_LEN];
@@ -113,6 +160,7 @@ struct wps_registrar {
        void *cb_ctx;
 
        struct dl_list pins;
+       struct dl_list nfc_pw_tokens;
        struct wps_pbc_session *pbc_sessions;
 
        int skip_cred_build;
@@ -591,6 +639,7 @@ wps_registrar_init(struct wps_context *wps,
                return NULL;
 
        dl_list_init(&reg->pins);
+       dl_list_init(&reg->nfc_pw_tokens);
        reg->wps = wps;
        reg->new_psk_cb = cfg->new_psk_cb;
        reg->set_ie_cb = cfg->set_ie_cb;
@@ -634,6 +683,7 @@ void wps_registrar_deinit(struct wps_registrar *reg)
        eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL);
        eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL);
        wps_free_pins(&reg->pins);
+       wps_free_nfc_pw_tokens(&reg->nfc_pw_tokens, 0);
        wps_free_pbc_sessions(reg->pbc_sessions);
        wpabuf_free(reg->extra_cred);
        wps_free_devices(reg->devices);
@@ -1255,6 +1305,13 @@ static int wps_get_dev_password(struct wps_data *wps)
                wpa_printf(MSG_DEBUG, "WPS: Use default PIN for PBC");
                pin = (const u8 *) "00000000";
                pin_len = 8;
+#ifdef CONFIG_WPS_NFC
+       } else if (wps->nfc_pw_token) {
+               wpa_printf(MSG_DEBUG, "WPS: Use OOB Device Password from NFC "
+                          "Password Token");
+               pin = wps->nfc_pw_token->dev_pw;
+               pin_len = wps->nfc_pw_token->dev_pw_len;
+#endif /* CONFIG_WPS_NFC */
        } else {
                pin = wps_registrar_get_pin(wps->wps->registrar, wps->uuid_e,
                                            &pin_len);
@@ -2441,8 +2498,34 @@ static enum wps_process_res wps_process_m1(struct wps_data *wps,
                return WPS_CONTINUE;
        }
 
+#ifdef CONFIG_WPS_NFC
+       if (wps->dev_pw_id >= 0x10) {
+               struct wps_nfc_pw_token *token;
+               const u8 *addr[1];
+               u8 hash[WPS_HASH_LEN];
+
+               token = wps_get_nfc_pw_token(
+                       &wps->wps->registrar->nfc_pw_tokens, wps->dev_pw_id);
+               if (token) {
+                       wpa_printf(MSG_DEBUG, "WPS: Found matching NFC "
+                                  "Password Token");
+                       dl_list_del(&token->list);
+                       wps->nfc_pw_token = token;
+
+                       addr[0] = attr->public_key;
+                       sha256_vector(1, addr, &attr->public_key_len, hash);
+                       if (os_memcmp(hash, wps->nfc_pw_token->pubkey_hash,
+                                     WPS_OOB_PUBKEY_HASH_LEN) != 0) {
+                               wpa_printf(MSG_ERROR, "WPS: Public Key hash "
+                                          "mismatch");
+                               return WPS_FAILURE;
+                       }
+               }
+       }
+#endif /* CONFIG_WPS_NFC */
+
 #ifdef CONFIG_WPS_OOB
-       if (wps->dev_pw_id >= 0x10 &&
+       if (wps->dev_pw_id >= 0x10 && wps->nfc_pw_token == NULL &&
            wps->dev_pw_id != wps->wps->oob_dev_pw_id) {
                wpa_printf(MSG_DEBUG, "WPS: OOB Device Password ID "
                           "%d mismatch", wps->dev_pw_id);
@@ -3369,6 +3452,43 @@ int wps_registrar_config_ap(struct wps_registrar *reg,
 
 
 #ifdef CONFIG_WPS_NFC
+
+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)
+{
+       struct wps_nfc_pw_token *token;
+
+       if (dev_pw_len > WPS_OOB_DEVICE_PASSWORD_LEN)
+               return -1;
+
+       wps_free_nfc_pw_tokens(&reg->nfc_pw_tokens, pw_id);
+
+       token = os_zalloc(sizeof(*token));
+       if (token == NULL)
+               return -1;
+
+       os_memcpy(token->pubkey_hash, pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN);
+       token->pw_id = pw_id;
+       os_memcpy(token->dev_pw, dev_pw, dev_pw_len);
+       token->dev_pw_len = dev_pw_len;
+
+       dl_list_add(&reg->nfc_pw_tokens, &token->list);
+
+       reg->selected_registrar = 1;
+       reg->pbc = 0;
+       wps_registrar_add_authorized_mac(reg,
+                                        (u8 *) "\xff\xff\xff\xff\xff\xff");
+       wps_registrar_selected_registrar_changed(reg);
+       eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL);
+       eloop_register_timeout(WPS_PBC_WALK_TIME, 0,
+                              wps_registrar_set_selected_timeout,
+                              reg, NULL);
+
+       return 0;
+}
+
+
 int wps_registrar_add_nfc_password_token(struct wps_registrar *reg,
                                         const u8 *oob_dev_pw,
                                         size_t oob_dev_pw_len)
@@ -3396,12 +3516,17 @@ int wps_registrar_add_nfc_password_token(struct wps_registrar *reg,
                    hash, WPS_OOB_PUBKEY_HASH_LEN);
        wpa_hexdump_key(MSG_DEBUG, "WPS: Device Password", dev_pw, dev_pw_len);
 
-       reg->wps->oob_dev_pw_id = id;
-       wpabuf_free(reg->wps->oob_conf.pubkey_hash);
-       reg->wps->oob_conf.pubkey_hash = wpabuf_alloc_copy(
-               hash, WPS_OOB_PUBKEY_HASH_LEN);
-       if (reg->wps->oob_conf.pubkey_hash == NULL)
-               return -1;
-       return wps_registrar_add_pin(reg, NULL, NULL, dev_pw, dev_pw_len, 300);
+       return wps_registrar_add_nfc_pw_token(reg, hash, id, dev_pw,
+                                             dev_pw_len);
 }
+
+
+void wps_registrar_remove_nfc_pw_token(struct wps_registrar *reg,
+                                      struct wps_nfc_pw_token *token)
+{
+       wps_registrar_remove_authorized_mac(reg,
+                                           (u8 *) "\xff\xff\xff\xff\xff\xff");
+       wps_registrar_selected_registrar_changed(reg);
+}
+
 #endif /* CONFIG_WPS_NFC */