]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
DPP: Add DPP Status attribute into Peer Discovery Response
authorJouni Malinen <jouni@qca.qualcomm.com>
Sun, 29 Oct 2017 09:43:41 +0000 (11:43 +0200)
committerJouni Malinen <j@w1.fi>
Sun, 29 Oct 2017 10:16:15 +0000 (12:16 +0200)
This was added in DPP tech spec v0.2.7 to allow result of network
introduction to be reported.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
src/ap/dpp_hostapd.c
src/common/dpp.c
src/common/dpp.h
src/common/wpa_ctrl.h
wpa_supplicant/dpp_supplicant.c

index b8b04749bf7e591c8a80b2c65fdb982c984b543c..943e20648db9a7ce55b4d6026144ba5743c93059 100644 (file)
@@ -890,6 +890,46 @@ static void hostapd_dpp_rx_auth_conf(struct hostapd_data *hapd, const u8 *src,
 }
 
 
+static void hostapd_dpp_send_peer_disc_resp(struct hostapd_data *hapd,
+                                           const u8 *src, unsigned int freq,
+                                           u8 trans_id,
+                                           enum dpp_status_error status)
+{
+       struct wpabuf *msg;
+
+       msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_RESP,
+                           5 + 5 + 4 + os_strlen(hapd->conf->dpp_connector));
+       if (!msg)
+               return;
+
+       /* Transaction ID */
+       wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
+       wpabuf_put_le16(msg, 1);
+       wpabuf_put_u8(msg, trans_id);
+
+       /* DPP Status */
+       wpabuf_put_le16(msg, DPP_ATTR_STATUS);
+       wpabuf_put_le16(msg, 1);
+       wpabuf_put_u8(msg, status);
+
+       /* DPP Connector */
+       if (status == DPP_STATUS_OK) {
+               wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
+               wpabuf_put_le16(msg, os_strlen(hapd->conf->dpp_connector));
+               wpabuf_put_str(msg, hapd->conf->dpp_connector);
+       }
+
+       wpa_printf(MSG_DEBUG, "DPP: Send Peer Discovery Response to " MACSTR
+                  " status=%d", MAC2STR(src), status);
+       wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
+               " freq=%u type=%d status=%d", MAC2STR(src), freq,
+               DPP_PA_PEER_DISCOVERY_RESP, status);
+       hostapd_drv_send_action(hapd, freq, 0, src,
+                               wpabuf_head(msg), wpabuf_len(msg));
+       wpabuf_free(msg);
+}
+
+
 static void hostapd_dpp_rx_peer_disc_req(struct hostapd_data *hapd,
                                         const u8 *src,
                                         const u8 *buf, size_t len,
@@ -901,7 +941,7 @@ static void hostapd_dpp_rx_peer_disc_req(struct hostapd_data *hapd,
        struct dpp_introduction intro;
        os_time_t expire;
        int expiration;
-       struct wpabuf *msg;
+       enum dpp_status_error res;
 
        wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Request from " MACSTR,
                   MAC2STR(src));
@@ -941,14 +981,24 @@ static void hostapd_dpp_rx_peer_disc_req(struct hostapd_data *hapd,
                return;
        }
 
-       if (dpp_peer_intro(&intro, hapd->conf->dpp_connector,
-                          wpabuf_head(hapd->conf->dpp_netaccesskey),
-                          wpabuf_len(hapd->conf->dpp_netaccesskey),
-                          wpabuf_head(hapd->conf->dpp_csign),
-                          wpabuf_len(hapd->conf->dpp_csign),
-                          connector, connector_len, &expire) < 0) {
+       res = dpp_peer_intro(&intro, hapd->conf->dpp_connector,
+                            wpabuf_head(hapd->conf->dpp_netaccesskey),
+                            wpabuf_len(hapd->conf->dpp_netaccesskey),
+                            wpabuf_head(hapd->conf->dpp_csign),
+                            wpabuf_len(hapd->conf->dpp_csign),
+                            connector, connector_len, &expire);
+       if (res == 255) {
+               wpa_printf(MSG_INFO,
+                          "DPP: Network Introduction protocol resulted in internal failure (peer "
+                          MACSTR ")", MAC2STR(src));
+               return;
+       }
+       if (res != DPP_STATUS_OK) {
                wpa_printf(MSG_INFO,
-                          "DPP: Network Introduction protocol resulted in failure");
+                          "DPP: Network Introduction protocol resulted in failure (peer "
+                          MACSTR " status %d)", MAC2STR(src), res);
+               hostapd_dpp_send_peer_disc_resp(hapd, src, freq, trans_id[0],
+                                               res);
                return;
        }
 
@@ -966,29 +1016,8 @@ static void hostapd_dpp_rx_peer_disc_req(struct hostapd_data *hapd,
                return;
        }
 
-       msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_RESP,
-                           5 + 4 + os_strlen(hapd->conf->dpp_connector));
-       if (!msg)
-               return;
-
-       /* Transaction ID */
-       wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
-       wpabuf_put_le16(msg, 1);
-       wpabuf_put_u8(msg, trans_id[0]);
-
-       /* DPP Connector */
-       wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
-       wpabuf_put_le16(msg, os_strlen(hapd->conf->dpp_connector));
-       wpabuf_put_str(msg, hapd->conf->dpp_connector);
-
-       wpa_printf(MSG_DEBUG, "DPP: Send Peer Discovery Response to " MACSTR,
-                  MAC2STR(src));
-       wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
-               " freq=%u type=%d", MAC2STR(src), freq,
-               DPP_PA_PEER_DISCOVERY_RESP);
-       hostapd_drv_send_action(hapd, freq, 0, src,
-                               wpabuf_head(msg), wpabuf_len(msg));
-       wpabuf_free(msg);
+       hostapd_dpp_send_peer_disc_resp(hapd, src, freq, trans_id[0],
+                                       DPP_STATUS_OK);
 }
 
 
index ae5fbd384748cdad4c2e6ee033e693390426bc77..f969cb35f018d0af7b4d84e01c14a08505618ef2 100644 (file)
@@ -4356,11 +4356,11 @@ struct dpp_signed_connector_info {
        size_t payload_len;
 };
 
-static int
+static enum dpp_status_error
 dpp_process_signed_connector(struct dpp_signed_connector_info *info,
                             EVP_PKEY *csign_pub, const char *connector)
 {
-       int ret = -1;
+       enum dpp_status_error ret = 255;
        const char *pos, *end, *signed_start, *signed_end;
        struct wpabuf *kid = NULL;
        unsigned char *prot_hdr = NULL, *signature = NULL;
@@ -4394,6 +4394,7 @@ dpp_process_signed_connector(struct dpp_signed_connector_info *info,
        end = os_strchr(pos, '.');
        if (!end) {
                wpa_printf(MSG_DEBUG, "DPP: Missing dot(1) in signedConnector");
+               ret = DPP_STATUS_INVALID_CONNECTOR;
                goto fail;
        }
        prot_hdr = base64_url_decode((const unsigned char *) pos,
@@ -4401,18 +4402,22 @@ dpp_process_signed_connector(struct dpp_signed_connector_info *info,
        if (!prot_hdr) {
                wpa_printf(MSG_DEBUG,
                           "DPP: Failed to base64url decode signedConnector JWS Protected Header");
+               ret = DPP_STATUS_INVALID_CONNECTOR;
                goto fail;
        }
        wpa_hexdump_ascii(MSG_DEBUG,
                          "DPP: signedConnector - JWS Protected Header",
                          prot_hdr, prot_hdr_len);
        kid = dpp_parse_jws_prot_hdr(curve, prot_hdr, prot_hdr_len, &sign_md);
-       if (!kid)
+       if (!kid) {
+               ret = DPP_STATUS_INVALID_CONNECTOR;
                goto fail;
+       }
        if (wpabuf_len(kid) != SHA256_MAC_LEN) {
                wpa_printf(MSG_DEBUG,
                           "DPP: Unexpected signedConnector JWS Protected Header kid length: %u (expected %u)",
                           (unsigned int) wpabuf_len(kid), SHA256_MAC_LEN);
+               ret = DPP_STATUS_INVALID_CONNECTOR;
                goto fail;
        }
 
@@ -4421,6 +4426,7 @@ dpp_process_signed_connector(struct dpp_signed_connector_info *info,
        if (!end) {
                wpa_printf(MSG_DEBUG,
                           "DPP: Missing dot(2) in signedConnector");
+               ret = DPP_STATUS_INVALID_CONNECTOR;
                goto fail;
        }
        signed_end = end - 1;
@@ -4429,6 +4435,7 @@ dpp_process_signed_connector(struct dpp_signed_connector_info *info,
        if (!info->payload) {
                wpa_printf(MSG_DEBUG,
                           "DPP: Failed to base64url decode signedConnector JWS Payload");
+               ret = DPP_STATUS_INVALID_CONNECTOR;
                goto fail;
        }
        wpa_hexdump_ascii(MSG_DEBUG,
@@ -4440,18 +4447,22 @@ dpp_process_signed_connector(struct dpp_signed_connector_info *info,
        if (!signature) {
                wpa_printf(MSG_DEBUG,
                           "DPP: Failed to base64url decode signedConnector signature");
+               ret = DPP_STATUS_INVALID_CONNECTOR;
                goto fail;
                }
        wpa_hexdump(MSG_DEBUG, "DPP: signedConnector - signature",
                    signature, signature_len);
 
-       if (dpp_check_pubkey_match(csign_pub, kid) < 0)
+       if (dpp_check_pubkey_match(csign_pub, kid) < 0) {
+               ret = DPP_STATUS_NO_MATCH;
                goto fail;
+       }
 
        if (signature_len & 0x01) {
                wpa_printf(MSG_DEBUG,
                           "DPP: Unexpected signedConnector signature length (%d)",
                           (int) signature_len);
+               ret = DPP_STATUS_INVALID_CONNECTOR;
                goto fail;
        }
 
@@ -4492,10 +4503,11 @@ dpp_process_signed_connector(struct dpp_signed_connector_info *info,
                wpa_printf(MSG_DEBUG,
                           "DPP: EVP_DigestVerifyFinal failed (res=%d): %s",
                           res, ERR_error_string(ERR_get_error(), NULL));
+               ret = DPP_STATUS_INVALID_CONNECTOR;
                goto fail;
        }
 
-       ret = 0;
+       ret = DPP_STATUS_OK;
 fail:
        EC_KEY_free(eckey);
        EVP_MD_CTX_destroy(md_ctx);
@@ -4554,7 +4566,7 @@ static int dpp_parse_cred_dpp(struct dpp_authentication *auth,
        }
 
        if (dpp_process_signed_connector(&info, csign_pub,
-                                        signed_connector) < 0)
+                                        signed_connector) != DPP_STATUS_OK)
                goto fail;
 
        if (dpp_parse_connector(auth, info.payload, info.payload_len) < 0) {
@@ -5021,15 +5033,16 @@ fail:
 }
 
 
-int dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector,
-                  const u8 *net_access_key, size_t net_access_key_len,
-                  const u8 *csign_key, size_t csign_key_len,
-                  const u8 *peer_connector, size_t peer_connector_len,
-                  os_time_t *expiry)
+enum dpp_status_error
+dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector,
+              const u8 *net_access_key, size_t net_access_key_len,
+              const u8 *csign_key, size_t csign_key_len,
+              const u8 *peer_connector, size_t peer_connector_len,
+              os_time_t *expiry)
 {
        struct json_token *root = NULL, *netkey, *token;
        struct json_token *own_root = NULL;
-       int ret = -1;
+       enum dpp_status_error ret = 255, res;
        EVP_PKEY *own_key = NULL, *peer_key = NULL;
        struct wpabuf *own_key_pub = NULL;
        const struct dpp_curve_params *curve, *own_curve;
@@ -5097,18 +5110,23 @@ int dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector,
        os_memcpy(signed_connector, peer_connector, peer_connector_len);
        signed_connector[peer_connector_len] = '\0';
 
-       if (dpp_process_signed_connector(&info, csign, signed_connector) < 0)
+       res = dpp_process_signed_connector(&info, csign, signed_connector);
+       if (res != DPP_STATUS_OK) {
+               ret = res;
                goto fail;
+       }
 
        root = json_parse((const char *) info.payload, info.payload_len);
        if (!root) {
                wpa_printf(MSG_DEBUG, "DPP: JSON parsing of connector failed");
+               ret = DPP_STATUS_INVALID_CONNECTOR;
                goto fail;
        }
 
        if (!dpp_connector_match_groups(own_root, root)) {
                wpa_printf(MSG_DEBUG,
                           "DPP: Peer connector does not include compatible group netrole with own connector");
+               ret = DPP_STATUS_NO_MATCH;
                goto fail;
        }
 
@@ -5121,6 +5139,7 @@ int dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector,
                if (dpp_key_expired(token->string, expiry)) {
                        wpa_printf(MSG_DEBUG,
                                   "DPP: Connector (netAccessKey) has expired");
+                       ret = DPP_STATUS_INVALID_CONNECTOR;
                        goto fail;
                }
        }
@@ -5128,18 +5147,22 @@ int dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector,
        netkey = json_get_member(root, "netAccessKey");
        if (!netkey || netkey->type != JSON_OBJECT) {
                wpa_printf(MSG_DEBUG, "DPP: No netAccessKey object found");
+               ret = DPP_STATUS_INVALID_CONNECTOR;
                goto fail;
        }
 
        peer_key = dpp_parse_jwk(netkey, &curve);
-       if (!peer_key)
+       if (!peer_key) {
+               ret = DPP_STATUS_INVALID_CONNECTOR;
                goto fail;
+       }
        dpp_debug_print_key("DPP: Received netAccessKey", peer_key);
 
        if (own_curve != curve) {
                wpa_printf(MSG_DEBUG,
                           "DPP: Mismatching netAccessKey curves (%s != %s)",
                           own_curve->name, curve->name);
+               ret = DPP_STATUS_INVALID_CONNECTOR;
                goto fail;
        }
 
@@ -5173,9 +5196,9 @@ int dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector,
                goto fail;
        }
 
-       ret = 0;
+       ret = DPP_STATUS_OK;
 fail:
-       if (ret < 0)
+       if (ret != DPP_STATUS_OK)
                os_memset(intro, 0, sizeof(*intro));
        os_memset(Nx, 0, sizeof(Nx));
        EVP_PKEY_CTX_free(ctx);
index 5f4922eee3af9fe117312bada8ad3d6b48ff16bc..905d1f138223bf26ad89e70a487cb0edb949da51 100644 (file)
@@ -63,6 +63,8 @@ enum dpp_status_error {
        DPP_STATUS_BAD_GROUP = 4,
        DPP_STATUS_CONFIGURE_FAILURE = 5,
        DPP_STATUS_RESPONSE_PENDING = 6,
+       DPP_STATUS_INVALID_CONNECTOR = 7,
+       DPP_STATUS_NO_MATCH = 8,
 };
 
 #define DPP_CAPAB_ENROLLEE BIT(0)
@@ -292,11 +294,12 @@ dpp_keygen_configurator(const char *curve, const u8 *privkey,
                        size_t privkey_len);
 int dpp_configurator_own_config(struct dpp_authentication *auth,
                                const char *curve);
-int dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector,
-                  const u8 *net_access_key, size_t net_access_key_len,
-                  const u8 *csign_key, size_t csign_key_len,
-                  const u8 *peer_connector, size_t peer_connector_len,
-                  os_time_t *expiry);
+enum dpp_status_error
+dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector,
+              const u8 *net_access_key, size_t net_access_key_len,
+              const u8 *csign_key, size_t csign_key_len,
+              const u8 *peer_connector, size_t peer_connector_len,
+              os_time_t *expiry);
 struct dpp_pkex * dpp_pkex_init(struct dpp_bootstrap_info *bi,
                                const u8 *own_mac,
                                const char *identifier,
index 18eeeb72698cb9b1af8b2ca3524197e4bd693777..6e9dcf14a615e956559dfc55faccdd3489265567 100644 (file)
@@ -171,6 +171,7 @@ extern "C" {
 #define DPP_EVENT_TX "DPP-TX "
 #define DPP_EVENT_TX_STATUS "DPP-TX-STATUS "
 #define DPP_EVENT_FAIL "DPP-FAIL "
+#define DPP_EVENT_INTRO "DPP-INTRO "
 
 /* MESH events */
 #define MESH_GROUP_STARTED "MESH-GROUP-STARTED "
index 0715556de018832bf63e6a394a6ea984f4c42e44..874b90992883f487729deeb0ccccd88d31dc32ea 100644 (file)
@@ -1243,14 +1243,15 @@ static void wpas_dpp_rx_peer_disc_resp(struct wpa_supplicant *wpa_s,
                                       const u8 *buf, size_t len)
 {
        struct wpa_ssid *ssid;
-       const u8 *connector, *trans_id;
-       u16 connector_len, trans_id_len;
+       const u8 *connector, *trans_id, *status;
+       u16 connector_len, trans_id_len, status_len;
        struct dpp_introduction intro;
        struct rsn_pmksa_cache_entry *entry;
        struct os_time now;
        struct os_reltime rnow;
        os_time_t expiry;
        unsigned int seconds;
+       enum dpp_status_error res;
 
        wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Response from " MACSTR,
                   MAC2STR(src));
@@ -1278,12 +1279,32 @@ static void wpas_dpp_rx_peer_disc_resp(struct wpa_supplicant *wpa_s,
        if (!trans_id || trans_id_len != 1) {
                wpa_printf(MSG_DEBUG,
                           "DPP: Peer did not include Transaction ID");
+               wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
+                       " fail=missing_transaction_id", MAC2STR(src));
                goto fail;
        }
        if (trans_id[0] != TRANSACTION_ID) {
                wpa_printf(MSG_DEBUG,
                           "DPP: Ignore frame with unexpected Transaction ID %u",
                           trans_id[0]);
+               wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
+                       " fail=transaction_id_mismatch", MAC2STR(src));
+               goto fail;
+       }
+
+       status = dpp_get_attr(buf, len, DPP_ATTR_STATUS, &status_len);
+       if (!status || status_len != 1) {
+               wpa_printf(MSG_DEBUG, "DPP: Peer did not include Status");
+               wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
+                       " fail=missing_status", MAC2STR(src));
+               goto fail;
+       }
+       if (status[0] != DPP_STATUS_OK) {
+               wpa_printf(MSG_DEBUG,
+                          "DPP: Peer rejected network introduction: Status %u",
+                          status[0]);
+               wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
+                       " status=%u", MAC2STR(src), status[0]);
                goto fail;
        }
 
@@ -1291,17 +1312,22 @@ static void wpas_dpp_rx_peer_disc_resp(struct wpa_supplicant *wpa_s,
        if (!connector) {
                wpa_printf(MSG_DEBUG,
                           "DPP: Peer did not include its Connector");
-               return;
+               wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
+                       " fail=missing_connector", MAC2STR(src));
+               goto fail;
        }
 
-       if (dpp_peer_intro(&intro, ssid->dpp_connector,
-                          ssid->dpp_netaccesskey,
-                          ssid->dpp_netaccesskey_len,
-                          ssid->dpp_csign,
-                          ssid->dpp_csign_len,
-                          connector, connector_len, &expiry) < 0) {
+       res = dpp_peer_intro(&intro, ssid->dpp_connector,
+                            ssid->dpp_netaccesskey,
+                            ssid->dpp_netaccesskey_len,
+                            ssid->dpp_csign,
+                            ssid->dpp_csign_len,
+                            connector, connector_len, &expiry);
+       if (res != DPP_STATUS_OK) {
                wpa_printf(MSG_INFO,
                           "DPP: Network Introduction protocol resulted in failure");
+               wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
+                       " fail=peer_connector_validation_failed", MAC2STR(src));
                goto fail;
        }
 
@@ -1325,6 +1351,9 @@ static void wpas_dpp_rx_peer_disc_resp(struct wpa_supplicant *wpa_s,
        entry->network_ctx = ssid;
        wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
 
+       wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
+               " status=%u", MAC2STR(src), status[0]);
+
        wpa_printf(MSG_DEBUG,
                   "DPP: Try connection again after successful network introduction");
        if (wpa_supplicant_fast_associate(wpa_s) != 1) {