]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
DPP2: Reconfig Authentication Confirm processing
authorJouni Malinen <jouni@codeaurora.org>
Sun, 10 May 2020 20:46:41 +0000 (23:46 +0300)
committerJouni Malinen <j@w1.fi>
Mon, 11 May 2020 14:26:11 +0000 (17:26 +0300)
Extend Enrollee functionality to process Reconfig Authentication
Confirm message and start GAS client.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
src/common/dpp.c
src/common/dpp.h
src/common/dpp_reconfig.c
wpa_supplicant/dpp_supplicant.c

index ff63256a4d019bdcbf48bbc20a76b25225d1df47..9aa42f1c71293bf4af260c75b05f65184c81c697 100644 (file)
@@ -4756,8 +4756,15 @@ static void dpp_copy_netaccesskey(struct dpp_authentication *auth,
        unsigned char *der = NULL;
        int der_len;
        EC_KEY *eckey;
+       EVP_PKEY *own_key;
 
-       eckey = EVP_PKEY_get1_EC_KEY(auth->own_protocol_key);
+       own_key = auth->own_protocol_key;
+#ifdef CONFIG_DPP2
+       if (auth->reconfig_connector_key == DPP_CONFIG_REUSEKEY &&
+           auth->reconfig_old_protocol_key)
+               own_key = auth->reconfig_old_protocol_key;
+#endif /* CONFIG_DPP2 */
+       eckey = EVP_PKEY_get1_EC_KEY(own_key);
        if (!eckey)
                return;
 
index d24e2f8881af0ac54161e58620b7123c19c43ad0..07c5bef6231b0fbcbddad448468dd689f0565cf1 100644 (file)
@@ -243,6 +243,7 @@ struct dpp_authentication {
        u8 waiting_pubkey_hash[SHA256_MAC_LEN];
        int response_pending;
        int reconfig;
+       enum dpp_connector_key reconfig_connector_key;
        enum dpp_status_error auth_resp_status;
        enum dpp_status_error conf_resp_status;
        u8 peer_mac_addr[ETH_ALEN];
@@ -661,6 +662,8 @@ dpp_reconfig_auth_req_rx(struct dpp_global *dpp, void *msg_ctx,
 struct wpabuf *
 dpp_reconfig_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr,
                          const u8 *attr_start, size_t attr_len);
+int dpp_reconfig_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr,
+                             const u8 *attr_start, size_t attr_len);
 
 #endif /* CONFIG_DPP */
 #endif /* DPP_H */
index 0db0e08b9fa03b23c278e17c7df5cc7a59c7bdf9..355114cbc2d4a6d1360663a596bc81e90c104e08 100644 (file)
@@ -754,4 +754,128 @@ fail:
        goto out;
 }
 
+
+int dpp_reconfig_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr,
+                             const u8 *attr_start, size_t attr_len)
+{
+       const u8 *trans_id, *version, *wrapped_data, *i_nonce, *r_nonce,
+               *reconfig_flags;
+       u16 trans_id_len, version_len, wrapped_data_len, i_nonce_len,
+               r_nonce_len, reconfig_flags_len;
+       const u8 *addr[2];
+       size_t len[2];
+       u8 *unwrapped = NULL;
+       size_t unwrapped_len = 0;
+       struct json_token *root = NULL, *token;
+       int res = -1;
+
+       if (!auth->reconfig || auth->configurator)
+               goto fail;
+
+       wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA,
+                                   &wrapped_data_len);
+       if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
+               dpp_auth_fail(auth,
+                             "Missing or invalid required Wrapped Data attribute");
+               goto fail;
+       }
+       wpa_hexdump(MSG_MSGDUMP, "DPP: Wrapped Data",
+                   wrapped_data, wrapped_data_len);
+
+       addr[0] = hdr;
+       len[0] = DPP_HDR_LEN;
+       addr[1] = attr_start;
+       len[1] = 0;
+       wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
+       wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
+       wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
+                   wrapped_data, wrapped_data_len);
+       unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
+       unwrapped = os_malloc(unwrapped_len);
+       if (!unwrapped)
+               goto fail;
+       if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
+                           wrapped_data, wrapped_data_len,
+                           2, addr, len, unwrapped) < 0) {
+               dpp_auth_fail(auth, "AES-SIV decryption failed");
+               goto fail;
+       }
+       wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
+                   unwrapped, unwrapped_len);
+
+       if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
+               dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
+               goto fail;
+       }
+
+       trans_id = dpp_get_attr(unwrapped, unwrapped_len,
+                               DPP_ATTR_TRANSACTION_ID, &trans_id_len);
+       if (!trans_id || trans_id_len != 1 ||
+           trans_id[0] != auth->transaction_id) {
+               dpp_auth_fail(auth,
+                             "Peer did not include valid Transaction ID");
+               goto fail;
+       }
+
+       version = dpp_get_attr(unwrapped, unwrapped_len,
+                              DPP_ATTR_PROTOCOL_VERSION, &version_len);
+       if (!version || version_len < 1 || version[0] != DPP_VERSION) {
+               dpp_auth_fail(auth,
+                             "Missing or invalid Protocol Version attribute");
+               goto fail;
+       }
+
+       i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE,
+                              &i_nonce_len);
+       if (!i_nonce || i_nonce_len != auth->curve->nonce_len ||
+           os_memcmp(i_nonce, auth->i_nonce, i_nonce_len) != 0) {
+               dpp_auth_fail(auth, "Missing or invalid I-nonce");
+               goto fail;
+       }
+       wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len);
+
+       r_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_NONCE,
+                              &r_nonce_len);
+       if (!r_nonce || r_nonce_len != auth->curve->nonce_len ||
+           os_memcmp(r_nonce, auth->r_nonce, r_nonce_len) != 0) {
+               dpp_auth_fail(auth, "Missing or invalid R-nonce");
+               goto fail;
+       }
+       wpa_hexdump(MSG_DEBUG, "DPP: R-nonce", r_nonce, r_nonce_len);
+
+       reconfig_flags = dpp_get_attr(unwrapped, unwrapped_len,
+                                     DPP_ATTR_RECONFIG_FLAGS,
+                                     &reconfig_flags_len);
+       if (!reconfig_flags) {
+               dpp_auth_fail(auth, "Missing or invalid Reconfig-Flags");
+               goto fail;
+       }
+       wpa_hexdump_ascii(MSG_DEBUG, "DPP: Reconfig-Flags",
+                         reconfig_flags, reconfig_flags_len);
+       root = json_parse((const char *) reconfig_flags, reconfig_flags_len);
+       if (!root) {
+               dpp_auth_fail(auth, "Could not parse Reconfig-Flags");
+               goto fail;
+       }
+       token = json_get_member(root, "connectorKey");
+       if (!token || token->type != JSON_NUMBER) {
+               dpp_auth_fail(auth, "No connectorKey in Reconfig-Flags");
+               goto fail;
+       }
+       if (token->number != DPP_CONFIG_REUSEKEY &&
+           token->number != DPP_CONFIG_REPLACEKEY) {
+               dpp_auth_fail(auth,
+                             "Unsupported connectorKey value in Reconfig-Flags");
+               goto fail;
+       }
+       auth->reconfig_connector_key = token->number;
+
+       auth->reconfig_success = true;
+       res = 0;
+fail:
+       json_free(root);
+       bin_clear_free(unwrapped, unwrapped_len);
+       return res;
+}
+
 #endif /* CONFIG_DPP2 */
index 8fd6ece79a91e71cad57e47a15c9bfb96d493cac..ae93d59fdb4404c142f0d7904a388430c72d6964 100644 (file)
@@ -1374,7 +1374,8 @@ static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
 
        wpa_s->dpp_gas_dialog_token = -1;
 
-       if (!auth || !auth->auth_success) {
+       if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
+           os_memcmp(addr, auth->peer_mac_addr, ETH_ALEN) != 0) {
                wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
                return;
        }
@@ -2007,6 +2008,35 @@ wpas_dpp_rx_reconfig_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src,
        wpas_dpp_start_gas_server(wpa_s);
 }
 
+
+static void
+wpas_dpp_rx_reconfig_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src,
+                              const u8 *hdr, const u8 *buf, size_t len,
+                              unsigned int freq)
+{
+       struct dpp_authentication *auth = wpa_s->dpp_auth;
+
+       wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Confirm from "
+                  MACSTR, MAC2STR(src));
+
+       if (!auth || !auth->reconfig || auth->configurator) {
+               wpa_printf(MSG_DEBUG,
+                          "DPP: No DPP Reconfig Authentication in progress - drop");
+               return;
+       }
+
+       if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
+               wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
+                          MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
+               return;
+       }
+
+       if (dpp_reconfig_auth_conf_rx(auth, hdr, buf, len) < 0)
+               return;
+
+       wpas_dpp_start_gas_client(wpa_s);
+}
+
 #endif /* CONFIG_DPP2 */
 
 
@@ -2578,6 +2608,9 @@ void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src,
        case DPP_PA_RECONFIG_AUTH_RESP:
                wpas_dpp_rx_reconfig_auth_resp(wpa_s, src, hdr, buf, len, freq);
                break;
+       case DPP_PA_RECONFIG_AUTH_CONF:
+               wpas_dpp_rx_reconfig_auth_conf(wpa_s, src, hdr, buf, len, freq);
+               break;
 #endif /* CONFIG_DPP2 */
        default:
                wpa_printf(MSG_DEBUG,