]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
WPS NFC: Use abbreviated handshake if both PK hashes delivered OOB
authorJouni Malinen <jouni@qca.qualcomm.com>
Sun, 24 Feb 2013 15:30:18 +0000 (17:30 +0200)
committerJouni Malinen <j@w1.fi>
Mon, 27 Jan 2014 19:10:55 +0000 (21:10 +0200)
When both the Registrar and Enrollee public key hashes are delivered
out-of-band (in NFC connection handover), use abbreviated WPS handshake
(skip M3-M8).

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>

src/wps/wps.h
src/wps/wps_enrollee.c
src/wps/wps_registrar.c

index 7e609c8319dc8fcd7f097679fefc097df727b747..c093b26d1ad5e1041c805f1331611050cb3ff2fe 100644 (file)
@@ -806,7 +806,8 @@ 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);
+                                  const u8 *dev_pw, size_t dev_pw_len,
+                                  int pk_hash_provided_oob);
 int wps_registrar_add_nfc_password_token(struct wps_registrar *reg,
                                         const u8 *oob_dev_pw,
                                         size_t oob_dev_pw_len);
index 03005822c5fb4eb31e8197924f286c0873edb31a..5d63c4c08cdce17c9cc4eede047c54c652893150 100644 (file)
@@ -946,6 +946,38 @@ static enum wps_process_res wps_process_m2(struct wps_data *wps,
                return WPS_CONTINUE;
        }
 
+#ifdef CONFIG_WPS_NFC
+       if (wps->peer_pubkey_hash_set) {
+               struct wpabuf *decrypted;
+               struct wps_parse_attr eattr;
+
+               decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings,
+                                                     attr->encr_settings_len);
+               if (decrypted == NULL) {
+                       wpa_printf(MSG_DEBUG, "WPS: Failed to decrypt "
+                                  "Encrypted Settings attribute");
+                       wps->state = SEND_WSC_NACK;
+                       return WPS_CONTINUE;
+               }
+
+               wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted "
+                          "Settings attribute");
+               if (wps_parse_msg(decrypted, &eattr) < 0 ||
+                   wps_process_key_wrap_auth(wps, decrypted,
+                                             eattr.key_wrap_auth) ||
+                   wps_process_creds(wps, eattr.cred, eattr.cred_len,
+                                     eattr.num_cred, attr->version2 != NULL)) {
+                       wpabuf_free(decrypted);
+                       wps->state = SEND_WSC_NACK;
+                       return WPS_CONTINUE;
+               }
+               wpabuf_free(decrypted);
+
+               wps->state = WPS_MSG_DONE;
+               return WPS_CONTINUE;
+       }
+#endif /* CONFIG_WPS_NFC */
+
        wps->state = SEND_M3;
        return WPS_CONTINUE;
 }
index 61bb6415b03faecdb59199aaa0721fb936feae1e..b8709b9f7b2a5434c03ab3a0adaf48376454a337 100644 (file)
@@ -34,6 +34,7 @@ struct wps_nfc_pw_token {
        u16 pw_id;
        u8 dev_pw[WPS_OOB_DEVICE_PASSWORD_LEN * 2 + 1];
        size_t dev_pw_len;
+       int pk_hash_provided_oob; /* whether own PK hash was provided OOB */
 };
 
 
@@ -1777,6 +1778,7 @@ static struct wpabuf * wps_build_ap_cred(struct wps_data *wps)
 static struct wpabuf * wps_build_m2(struct wps_data *wps)
 {
        struct wpabuf *msg;
+       int config_in_m2 = 0;
 
        if (random_get_bytes(wps->nonce_r, WPS_NONCE_LEN) < 0)
                return NULL;
@@ -1807,14 +1809,40 @@ static struct wpabuf * wps_build_m2(struct wps_data *wps)
            wps_build_config_error(msg, WPS_CFG_NO_ERROR) ||
            wps_build_dev_password_id(msg, wps->dev_pw_id) ||
            wps_build_os_version(&wps->wps->dev, msg) ||
-           wps_build_wfa_ext(msg, 0, NULL, 0) ||
-           wps_build_authenticator(wps, msg)) {
+           wps_build_wfa_ext(msg, 0, NULL, 0)) {
+               wpabuf_free(msg);
+               return NULL;
+       }
+
+#ifdef CONFIG_WPS_NFC
+       if (wps->nfc_pw_token && wps->nfc_pw_token->pk_hash_provided_oob) {
+               /*
+                * Use abbreviated handshake since public key hash allowed
+                * Enrollee to validate our public key similarly to how Enrollee
+                * public key was validated. There is no need to validate Device
+                * Password in this case.
+                */
+               struct wpabuf *plain = wpabuf_alloc(500);
+               if (plain == NULL ||
+                   wps_build_cred(wps, plain) ||
+                   wps_build_key_wrap_auth(wps, plain) ||
+                   wps_build_encr_settings(wps, msg, plain)) {
+                       wpabuf_free(msg);
+                       wpabuf_free(plain);
+                       return NULL;
+               }
+               wpabuf_free(plain);
+               config_in_m2 = 1;
+       }
+#endif /* CONFIG_WPS_NFC */
+
+       if (wps_build_authenticator(wps, msg)) {
                wpabuf_free(msg);
                return NULL;
        }
 
        wps->int_reg = 1;
-       wps->state = RECV_M3;
+       wps->state = config_in_m2 ? RECV_DONE : RECV_M3;
        return msg;
 }
 
@@ -3496,7 +3524,8 @@ int wps_registrar_config_ap(struct wps_registrar *reg,
 
 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)
+                                  const u8 *dev_pw, size_t dev_pw_len,
+                                  int pk_hash_provided_oob)
 {
        struct wps_nfc_pw_token *token;
 
@@ -3511,6 +3540,7 @@ int wps_registrar_add_nfc_pw_token(struct wps_registrar *reg,
 
        os_memcpy(token->pubkey_hash, pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN);
        token->pw_id = pw_id;
+       token->pk_hash_provided_oob = pk_hash_provided_oob;
        wpa_snprintf_hex_uppercase((char *) token->dev_pw,
                                   sizeof(token->dev_pw),
                                   dev_pw, dev_pw_len);
@@ -3563,7 +3593,7 @@ int wps_registrar_add_nfc_password_token(struct wps_registrar *reg,
        wpa_hexdump_key(MSG_DEBUG, "WPS: Device Password", dev_pw, dev_pw_len);
 
        return wps_registrar_add_nfc_pw_token(reg, hash, id, dev_pw,
-                                             dev_pw_len);
+                                             dev_pw_len, 0);
 }