From e5be6e68c8ea4cce1235a4870517f60a71ef9d20 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 6 Aug 2020 19:47:28 +0300 Subject: [PATCH] DPP2: Add Enrollee netAccessKey group into Reconfig Announcement This was added to the protocol design to support cases where the C-sign-key uses a different group than the netAccessKey. The Enrollee now indicates its netAccessKey group in Reconfig Announcement and the Configurator builds it own reconfig Connector using that group instead of the group used for the C-sign-key. Signed-off-by: Jouni Malinen --- src/ap/dpp_hostapd.c | 17 +++++++-- src/common/dpp.h | 6 ++-- src/common/dpp_crypto.c | 16 +++++++-- src/common/dpp_i.h | 1 + src/common/dpp_reconfig.c | 63 +++++++++++++++++++++++++-------- src/common/dpp_tcp.c | 17 +++++++-- wpa_supplicant/dpp_supplicant.c | 21 ++++++++--- 7 files changed, 113 insertions(+), 28 deletions(-) diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c index 178fd126e..ca225894a 100644 --- a/src/ap/dpp_hostapd.c +++ b/src/ap/dpp_hostapd.c @@ -1235,11 +1235,12 @@ hostapd_dpp_rx_reconfig_announcement(struct hostapd_data *hapd, const u8 *src, const u8 *hdr, const u8 *buf, size_t len, unsigned int freq) { - const u8 *csign_hash; - u16 csign_hash_len; + const u8 *csign_hash, *fcgroup; + u16 csign_hash_len, fcgroup_len; struct dpp_configurator *conf; struct dpp_authentication *auth; unsigned int wait_time, max_wait_time; + u16 group; if (hapd->dpp_auth) { wpa_printf(MSG_DEBUG, @@ -1271,8 +1272,18 @@ hostapd_dpp_rx_reconfig_announcement(struct hostapd_data *hapd, const u8 *src, return; } + fcgroup = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP, + &fcgroup_len); + if (!fcgroup || fcgroup_len != 2) { + wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL + "Missing or invalid required Finite Cyclic Group attribute"); + return; + } + group = WPA_GET_LE16(fcgroup); + wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group); + auth = dpp_reconfig_init(hapd->iface->interfaces->dpp, hapd->msg_ctx, - conf, freq); + conf, freq, group); if (!auth) return; hostapd_dpp_set_testing_options(hapd, auth); diff --git a/src/common/dpp.h b/src/common/dpp.h index cff996095..f6e4e25f2 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -683,10 +683,12 @@ void dpp_global_deinit(struct dpp_global *dpp); /* dpp_reconfig.c */ struct wpabuf * dpp_build_reconfig_announcement(const u8 *csign_key, - size_t csign_key_len); + size_t csign_key_len, + const u8 *net_access_key, + size_t net_access_key_len); struct dpp_authentication * dpp_reconfig_init(struct dpp_global *dpp, void *msg_ctx, - struct dpp_configurator *conf, unsigned int freq); + struct dpp_configurator *conf, unsigned int freq, u16 group); struct dpp_authentication * dpp_reconfig_auth_req_rx(struct dpp_global *dpp, void *msg_ctx, const char *own_connector, diff --git a/src/common/dpp_crypto.c b/src/common/dpp_crypto.c index e83ab9c60..6752aaa31 100644 --- a/src/common/dpp_crypto.c +++ b/src/common/dpp_crypto.c @@ -130,6 +130,18 @@ const struct dpp_curve_params * dpp_get_curve_nid(int nid) } +const struct dpp_curve_params * dpp_get_curve_ike_group(u16 group) +{ + int i; + + for (i = 0; dpp_curves[i].name; i++) { + if (dpp_curves[i].ike_group == group) + return &dpp_curves[i]; + } + return NULL; +} + + void dpp_debug_print_point(const char *title, const EC_GROUP *group, const EC_POINT *point) { @@ -2272,7 +2284,7 @@ int dpp_reconfig_derive_ke_responder(struct dpp_authentication *auth, if (auth->curve != curve) { wpa_printf(MSG_DEBUG, - "DPP: Mismatching netAccessKey curves (%s != %s)", + "DPP: Mismatching netAccessKey curves (own=%s != peer=%s)", auth->curve->name, curve->name); goto fail; } @@ -2381,7 +2393,7 @@ int dpp_reconfig_derive_ke_initiator(struct dpp_authentication *auth, dpp_debug_print_key("DPP: Received netAccessKey", peer_key); if (auth->curve != curve) { wpa_printf(MSG_DEBUG, - "DPP: Mismatching netAccessKey curves (%s != %s)", + "DPP: Mismatching netAccessKey curves (own=%s != peer=%s)", auth->curve->name, curve->name); goto fail; } diff --git a/src/common/dpp_i.h b/src/common/dpp_i.h index e66eb6cfd..cf3dedd01 100644 --- a/src/common/dpp_i.h +++ b/src/common/dpp_i.h @@ -73,6 +73,7 @@ dpp_check_signed_connector(struct dpp_signed_connector_info *info, const struct dpp_curve_params * dpp_get_curve_name(const char *name); const struct dpp_curve_params * dpp_get_curve_jwk_crv(const char *name); const struct dpp_curve_params * dpp_get_curve_nid(int nid); +const struct dpp_curve_params * dpp_get_curve_ike_group(u16 group); int dpp_bi_pubkey_hash(struct dpp_bootstrap_info *bi, const u8 *data, size_t data_len); struct wpabuf * dpp_get_pubkey_point(EVP_PKEY *pkey, int prefix); diff --git a/src/common/dpp_reconfig.c b/src/common/dpp_reconfig.c index 0bb00cc1d..5d7ab6802 100644 --- a/src/common/dpp_reconfig.c +++ b/src/common/dpp_reconfig.c @@ -34,9 +34,11 @@ static void dpp_build_attr_csign_key_hash(struct wpabuf *msg, const u8 *hash) struct wpabuf * dpp_build_reconfig_announcement(const u8 *csign_key, - size_t csign_key_len) + size_t csign_key_len, + const u8 *net_access_key, + size_t net_access_key_len) { - struct wpabuf *msg; + struct wpabuf *msg = NULL; EVP_PKEY *csign = NULL; const unsigned char *p; struct wpabuf *uncomp; @@ -44,39 +46,61 @@ struct wpabuf * dpp_build_reconfig_announcement(const u8 *csign_key, const u8 *addr[1]; size_t len[1]; int res; + size_t attr_len; + const struct dpp_curve_params *own_curve; + EVP_PKEY *own_key; wpa_printf(MSG_DEBUG, "DPP: Build Reconfig Announcement frame"); + own_key = dpp_set_keypair(&own_curve, net_access_key, + net_access_key_len); + if (!own_key) { + wpa_printf(MSG_ERROR, "DPP: Failed to parse own netAccessKey"); + goto fail; + } + p = csign_key; csign = d2i_PUBKEY(NULL, &p, csign_key_len); if (!csign) { wpa_printf(MSG_ERROR, "DPP: Failed to parse local C-sign-key information"); - return NULL; + goto fail; } uncomp = dpp_get_pubkey_point(csign, 1); EVP_PKEY_free(csign); if (!uncomp) - return NULL; + goto fail; addr[0] = wpabuf_head(uncomp); len[0] = wpabuf_len(uncomp); wpa_hexdump(MSG_DEBUG, "DPP: Uncompressed C-sign key", addr[0], len[0]); res = sha256_vector(1, addr, len, hash); wpabuf_free(uncomp); if (res < 0) - return NULL; + goto fail; wpa_hexdump(MSG_DEBUG, "DPP: kid = SHA256(uncompressed C-sign key)", hash, SHA256_MAC_LEN); - msg = dpp_alloc_msg(DPP_PA_RECONFIG_ANNOUNCEMENT, 4 + SHA256_MAC_LEN); + attr_len = 4 + SHA256_MAC_LEN; + attr_len += 4 + 2; + msg = dpp_alloc_msg(DPP_PA_RECONFIG_ANNOUNCEMENT, attr_len); if (!msg) - return NULL; + goto fail; /* Configurator C-sign key Hash */ dpp_build_attr_csign_key_hash(msg, hash); + + /* Finite Cyclic Group attribute */ + wpa_printf(MSG_DEBUG, "DPP: Finite Cyclic Group: %u", + own_curve->ike_group); + wpabuf_put_le16(msg, DPP_ATTR_FINITE_CYCLIC_GROUP); + wpabuf_put_le16(msg, 2); + wpabuf_put_le16(msg, own_curve->ike_group); + wpa_hexdump_buf(MSG_DEBUG, "DPP: Reconfig Announcement frame attributes", msg); +fail: + EVP_PKEY_free(own_key); return msg; } @@ -121,7 +145,9 @@ static struct wpabuf * dpp_reconfig_build_req(struct dpp_authentication *auth) } -static int dpp_configurator_build_own_connector(struct dpp_configurator *conf) +static int +dpp_configurator_build_own_connector(struct dpp_configurator *conf, + const struct dpp_curve_params *curve) { struct wpabuf *dppcon = NULL; int ret = -1; @@ -132,12 +158,12 @@ static int dpp_configurator_build_own_connector(struct dpp_configurator *conf) wpa_printf(MSG_DEBUG, "DPP: Sign own Configurator Connector for reconfiguration with curve %s", conf->curve->name); - conf->connector_key = dpp_gen_keypair(conf->curve); + conf->connector_key = dpp_gen_keypair(curve); if (!conf->connector_key) goto fail; /* Connector (JSON dppCon object) */ - dppcon = wpabuf_alloc(1000 + 2 * conf->curve->prime_len * 4 / 3); + dppcon = wpabuf_alloc(1000 + 2 * curve->prime_len * 4 / 3); if (!dppcon) goto fail; json_start_object(dppcon, NULL); @@ -150,7 +176,7 @@ static int dpp_configurator_build_own_connector(struct dpp_configurator *conf) json_end_array(dppcon); json_value_sep(dppcon); if (dpp_build_jwk(dppcon, "netAccessKey", conf->connector_key, NULL, - conf->curve) < 0) { + curve) < 0) { wpa_printf(MSG_DEBUG, "DPP: Failed to build netAccessKey JWK"); goto fail; } @@ -172,9 +198,18 @@ fail: struct dpp_authentication * dpp_reconfig_init(struct dpp_global *dpp, void *msg_ctx, - struct dpp_configurator *conf, unsigned int freq) + struct dpp_configurator *conf, unsigned int freq, u16 group) { struct dpp_authentication *auth; + const struct dpp_curve_params *curve; + + curve = dpp_get_curve_ike_group(group); + if (!curve) { + wpa_printf(MSG_DEBUG, + "DPP: Unsupported group %u - cannot reconfigure", + group); + return NULL; + } auth = dpp_alloc_auth(dpp, msg_ctx); if (!auth) @@ -186,12 +221,12 @@ dpp_reconfig_init(struct dpp_global *dpp, void *msg_ctx, auth->waiting_auth_resp = 1; auth->allowed_roles = DPP_CAPAB_CONFIGURATOR; auth->configurator = 1; - auth->curve = conf->curve; + auth->curve = curve; auth->transaction_id = 1; if (freq && dpp_prepare_channel_list(auth, freq, NULL, 0) < 0) goto fail; - if (dpp_configurator_build_own_connector(conf) < 0) + if (dpp_configurator_build_own_connector(conf, curve) < 0) goto fail; if (random_get_bytes(auth->i_nonce, auth->curve->nonce_len)) { diff --git a/src/common/dpp_tcp.c b/src/common/dpp_tcp.c index 9994c67cd..a4ec81398 100644 --- a/src/common/dpp_tcp.c +++ b/src/common/dpp_tcp.c @@ -844,11 +844,12 @@ static int dpp_controller_rx_reconfig_announcement(struct dpp_connection *conn, const u8 *hdr, const u8 *buf, size_t len) { - const u8 *csign_hash; - u16 csign_hash_len; + const u8 *csign_hash, *fcgroup; + u16 csign_hash_len, fcgroup_len; struct dpp_configurator *conf; struct dpp_global *dpp = conn->ctrl->global; struct dpp_authentication *auth; + u16 group; if (conn->auth) { wpa_printf(MSG_DEBUG, @@ -874,7 +875,17 @@ static int dpp_controller_rx_reconfig_announcement(struct dpp_connection *conn, return -1; } - auth = dpp_reconfig_init(dpp, dpp->msg_ctx, conf, 0); + fcgroup = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP, + &fcgroup_len); + if (!fcgroup || fcgroup_len != 2) { + wpa_msg(dpp->msg_ctx, MSG_INFO, DPP_EVENT_FAIL + "Missing or invalid required Finite Cyclic Group attribute"); + return -1; + } + group = WPA_GET_LE16(fcgroup); + wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group); + + auth = dpp_reconfig_init(dpp, dpp->msg_ctx, conf, 0, group); if (!auth) return -1; if (dpp_set_configurator(auth, conn->ctrl->configurator_params) < 0) { diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index cc35030c9..9c0056c5b 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -2022,11 +2022,12 @@ wpas_dpp_rx_reconfig_announcement(struct wpa_supplicant *wpa_s, const u8 *src, const u8 *hdr, const u8 *buf, size_t len, unsigned int freq) { - const u8 *csign_hash; - u16 csign_hash_len; + const u8 *csign_hash, *fcgroup; + u16 csign_hash_len, fcgroup_len; struct dpp_configurator *conf; struct dpp_authentication *auth; unsigned int wait_time, max_wait_time; + u16 group; if (!wpa_s->dpp) return; @@ -2056,7 +2057,17 @@ wpas_dpp_rx_reconfig_announcement(struct wpa_supplicant *wpa_s, const u8 *src, return; } - auth = dpp_reconfig_init(wpa_s->dpp, wpa_s, conf, freq); + fcgroup = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP, + &fcgroup_len); + if (!fcgroup || fcgroup_len != 2) { + wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL + "Missing or invalid required Finite Cyclic Group attribute"); + return; + } + group = WPA_GET_LE16(fcgroup); + wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group); + + auth = dpp_reconfig_init(wpa_s->dpp, wpa_s, conf, freq, group); if (!auth) return; wpas_dpp_set_testing_options(wpa_s, auth); @@ -3636,7 +3647,9 @@ int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) wpa_s->dpp_qr_mutual = 0; wpa_s->dpp_reconfig_announcement = dpp_build_reconfig_announcement(ssid->dpp_csign, - ssid->dpp_csign_len); + ssid->dpp_csign_len, + ssid->dpp_netaccesskey, + ssid->dpp_netaccesskey_len); if (!wpa_s->dpp_reconfig_announcement) return -1; wpa_s->dpp_reconfig_ssid = ssid;