From patchwork Thu Oct 26 20:26:43 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Prestwood X-Patchwork-Id: 13437856 Received: from mail-qk1-f181.google.com (mail-qk1-f181.google.com [209.85.222.181]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5E77A3CCFD for ; Thu, 26 Oct 2023 20:27:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="M/Xas49t" Received: by mail-qk1-f181.google.com with SMTP id af79cd13be357-778a108ae49so198479085a.0 for ; Thu, 26 Oct 2023 13:27:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1698352027; x=1698956827; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=MrJAgnVQwRPpzzzDsBMRhu+7IsVhw5HTRlf8DLudn5U=; b=M/Xas49t1h9JD2bieLd9EO/87Co/iR38JtvhWtWmEEEeH8zHVpWeUSj3sK1p0H7xWi 6HYekX4unaoz89R7cB1/FlK2EA/abeiTTRT3TQ7eaqSxXwyTOfayp+RPH4oAWU51tIRY 6DQjTVwEi2wOObShcjgcs+pd+AN3XcSqLLkBYIO37Z0Ta3ZmglyZVyPrw+FQq3i4iQay XuXk7W/4vnHvuQ4CyAKnQOXYKQp/ego+JG38jLKasPv+OMG2f7jKpjTQHzc3iX7jVs9p dGHGpUT0F0sBkdPUZNMlYsQ+6lT2tdO1f++GeSQqsPVhwyC3vTaIiuSxeoryxteJV1tg jXWQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698352027; x=1698956827; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=MrJAgnVQwRPpzzzDsBMRhu+7IsVhw5HTRlf8DLudn5U=; b=r93m5Xqk8hl6Ei3AxHi7J/RDCFXGPp9QvA6P84brsUV3Tg0d/aYx3cVljg3KaKW7/A xb416I+zEI8yi1fqM9UR+U6sWSXPwM67vg7I1erJhixPF1hnB7Mvhc8ejisWHdBiaW0J vc7HT1lv8aTdGxXbLiOF51i2Pi1TsvHC/g7cuas0zNxC+8DZtLhEy9+0a8XfmNYDo9x4 +RM3s5CfIi9h0679PSOmuKMR9iNmfl0Ba/3BaLXO1bgbAvkaP2eBURbFV0tfL1wHfFZV nf8xsL0FbXXmu/Qm7nVn5AHySql4iFXcknRKeCBtC3zdxSc+tWJ6RE4b2EdTaIkwfamb 1UIA== X-Gm-Message-State: AOJu0YyPBYChyDCPAReDLVJAoHoYtHxJgraO945t7eaVq6gEKYvSe7PU jGG5pqFKX0MsCArRDhFyL2BV9x/DxC8= X-Google-Smtp-Source: AGHT+IEZjEN9de5oq4hTVjM7fVcfCjSxQPORO4AoVKGcRVLvIUu/aoPvI27NB7WR72bbPGUW5CHXZA== X-Received: by 2002:a05:620a:408f:b0:76d:a784:9685 with SMTP id f15-20020a05620a408f00b0076da7849685mr1219029qko.28.1698352026847; Thu, 26 Oct 2023 13:27:06 -0700 (PDT) Received: from LOCLAP699.rst-02.locus (50-78-19-50-static.hfc.comcastbusiness.net. [50.78.19.50]) by smtp.gmail.com with ESMTPSA id r4-20020a05620a298400b007742c2ad7dfsm7303qkp.73.2023.10.26.13.27.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 26 Oct 2023 13:27:06 -0700 (PDT) From: James Prestwood To: iwd@lists.linux.dev Cc: James Prestwood Subject: [PATCH v2 01/15] station: add station_get_autoconnect Date: Thu, 26 Oct 2023 13:26:43 -0700 Message-Id: <20231026202657.183591-2-prestwoj@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231026202657.183591-1-prestwoj@gmail.com> References: <20231026202657.183591-1-prestwoj@gmail.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Getter for stations current autoconnect state --- src/station.c | 5 +++++ src/station.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/station.c b/src/station.c index 9b224e5a..2b88335c 100644 --- a/src/station.c +++ b/src/station.c @@ -1697,6 +1697,11 @@ bool station_set_autoconnect(struct station *station, bool autoconnect) return true; } +bool station_get_autoconnect(struct station *station) +{ + return station->autoconnect; +} + static void station_roam_state_clear(struct station *station) { l_debug("%u", netdev_get_ifindex(station->netdev)); diff --git a/src/station.h b/src/station.h index 24fab321..776641c6 100644 --- a/src/station.h +++ b/src/station.h @@ -87,6 +87,7 @@ uint32_t station_add_event_watch(station_event_watch_func_t func, void station_remove_event_watch(uint32_t id); bool station_set_autoconnect(struct station *station, bool autoconnect); +bool station_get_autoconnect(struct station *station); int __station_connect_network(struct station *station, struct network *network, struct scan_bss *bss); From patchwork Thu Oct 26 20:26:44 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Prestwood X-Patchwork-Id: 13437857 Received: from mail-qk1-f171.google.com (mail-qk1-f171.google.com [209.85.222.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B8F8D156CE for ; Thu, 26 Oct 2023 20:27:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="TouUj4XX" Received: by mail-qk1-f171.google.com with SMTP id af79cd13be357-7789577b53fso96149485a.3 for ; Thu, 26 Oct 2023 13:27:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1698352028; x=1698956828; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=QVKSeH84kKGR8hiFCBX3rFqpp2wx2B4B0cMq81CHutE=; b=TouUj4XXA+tG/CSNeZjvn8s/z2HbxtoM3VLHWresceheI9FT6Y+q/FUsvv40STOBc0 E9zPgVBU2sJtogrk13yrYznxeclXmrR+p8d2mbu5+Fv80pO2KatEuAMthkFYwpL48pF4 7+5krPDUK62TeuLNB8O2pMsZ3ipNrTOKoA6BbDQqRQRMiEPVSdAL618+TZeeCoQIsjAS IDdIfopQLcEO019qILdGNBfYzPcKeJcEpT3hykQrsxHoosZK2W5dZnpUC9kU9FfZgIVO OM6y+kBAf7d48/z5mh7MJpYkAS+0HePCWPVeNb8geiO7jC+w7/PNyxn2Fj5Od96CtONC iJbA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698352028; x=1698956828; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=QVKSeH84kKGR8hiFCBX3rFqpp2wx2B4B0cMq81CHutE=; b=ea9IAYpYdrYEhZ8uYwTny3/gaBT4ufgOol+8M58ckuNUYV/fQ8CB+LoAL5DCBxBvnO BeWMx1/kQcjDi/awKEs24DWct2fHNzGg63gN0qsBxsnaxutsvDLjBhjQZqJ5yg32GY77 zzPhGqKR9II3LbDElBYRSA4t2HBFAJZgORGnBJSkx+aOIHcwCNKBxX9tTnbgFlWeQbDN EAhL4vV47GZUzASURoSP5tz/sbb5hJCEzDt4Eu/wBbgeoNBrYLQn3ZNbI0JWoYKvnK9W +RO4UxWdAWcVw+aX7HeI57gQKyT78HldhYEijCho2/G2kxJRe/ZSvG/MZCfq8Y4Hf0im 81yg== X-Gm-Message-State: AOJu0Yzm+YZNdhIXvidel8bBvGRmG2wh10+3avH2oPZ4pLjRJAvYBAHF lKLJjqZvoWTcScLDlVq1DM1P9jxA8JI= X-Google-Smtp-Source: AGHT+IEFwHHhFFn6X62xTLfT6aRB//rfL8MN7n5s/dHbWx8SkRBKzuUBmX78zPxtkj4pBFx64Eqw/g== X-Received: by 2002:a05:620a:6014:b0:778:8fee:e863 with SMTP id dw20-20020a05620a601400b007788feee863mr447295qkb.75.1698352028467; Thu, 26 Oct 2023 13:27:08 -0700 (PDT) Received: from LOCLAP699.rst-02.locus (50-78-19-50-static.hfc.comcastbusiness.net. [50.78.19.50]) by smtp.gmail.com with ESMTPSA id r4-20020a05620a298400b007742c2ad7dfsm7303qkp.73.2023.10.26.13.27.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 26 Oct 2023 13:27:08 -0700 (PDT) From: James Prestwood To: iwd@lists.linux.dev Cc: James Prestwood Subject: [PATCH v2 02/15] dpp: remove connect/scanning and resume periodic scans after DPP Date: Thu, 26 Oct 2023 13:26:44 -0700 Message-Id: <20231026202657.183591-3-prestwoj@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231026202657.183591-1-prestwoj@gmail.com> References: <20231026202657.183591-1-prestwoj@gmail.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 When DPP is started periodic scans are stopped but never started again. This means if DPP fails IWD will never resume autoconnecting without some intervention. This also removes the internal scanning/connecting logic from DPP which was done for two reasons. First its unknown how long the DPP protocol took and its safest to explicitly scan to find the target network/bss, and second the connect logic was flawed because station will not transition into a CONNECTING state since __station_connect_network shortcuts the state change. If DPP failed station would never resume autoconnecting, and if the post-DPP connection failed the state was set incorrectly so station would also not resume autoconnecting. The downside of this is it takes slightly longer to connect after DPP since IWD must scan, but the DPP logic is simplified and keeps all connection logic in station.c where it belongs. --- src/dpp.c | 76 ++++++++++++++++++++----------------------------------- 1 file changed, 27 insertions(+), 49 deletions(-) diff --git a/src/dpp.c b/src/dpp.c index c93b9f1c..23b17d01 100644 --- a/src/dpp.c +++ b/src/dpp.c @@ -71,6 +71,7 @@ enum dpp_state { DPP_STATE_PRESENCE, DPP_STATE_AUTHENTICATING, DPP_STATE_CONFIGURING, + DPP_STATE_SUCCESS, }; enum dpp_capability { @@ -137,7 +138,6 @@ struct dpp_sm { struct l_timeout *timeout; struct dpp_configuration *config; - uint32_t connect_scan_id; uint64_t frame_cookie; uint8_t frame_retry; void *frame_pending; @@ -149,6 +149,7 @@ struct dpp_sm { bool mcast_support : 1; bool roc_started : 1; bool channel_switch : 1; + bool station_autoconnecting : 1; }; static bool dpp_get_started(struct l_dbus *dbus, @@ -270,6 +271,8 @@ static void dpp_free_auth_data(struct dpp_sm *dpp) static void dpp_reset(struct dpp_sm *dpp) { + struct station *station = station_find(netdev_get_ifindex(dpp->netdev)); + if (dpp->uri) { l_free(dpp->uri); dpp->uri = NULL; @@ -295,11 +298,6 @@ static void dpp_reset(struct dpp_sm *dpp) dpp->config = NULL; } - if (dpp->connect_scan_id) { - scan_cancel(dpp->wdev_id, dpp->connect_scan_id); - dpp->connect_scan_id = 0; - } - if (dpp->peer_asn1) { l_free(dpp->peer_asn1); dpp->peer_asn1 = NULL; @@ -315,7 +313,17 @@ static void dpp_reset(struct dpp_sm *dpp) dpp->retry_timeout = NULL; } + /* + * Set station back to its original autoconnecting state if an + * enrollee and DPP failed + */ + if (station && dpp->role == DPP_CAPABILITY_ENROLLEE && + dpp->station_autoconnecting && + dpp->state != DPP_STATE_SUCCESS) + station_set_autoconnect(station, true); + dpp->state = DPP_STATE_NOTHING; + dpp->role = 0; dpp->new_freq = 0; dpp->frame_retry = 0; dpp->frame_cookie = 0; @@ -629,36 +637,6 @@ static void dpp_write_config(struct dpp_configuration *config, storage_network_sync(SECURITY_PSK, ssid, settings); } -static void dpp_scan_triggered(int err, void *user_data) -{ - /* Not much can be done in this case */ - if (err < 0) - l_error("Failed to trigger DPP scan"); -} - -static bool dpp_scan_results(int err, struct l_queue *bss_list, - const struct scan_freq_set *freqs, - void *userdata) -{ - struct dpp_sm *dpp = userdata; - struct station *station = station_find(netdev_get_ifindex(dpp->netdev)); - - if (err < 0) - return false; - - station_set_scan_results(station, bss_list, freqs, true); - - return true; -} - -static void dpp_scan_destroy(void *userdata) -{ - struct dpp_sm *dpp = userdata; - - dpp->connect_scan_id = 0; - dpp_reset(dpp); -} - static void dpp_handle_config_response_frame(const struct mmpdu_header *frame, const void *body, size_t body_len, int rssi, void *user_data) @@ -685,7 +663,6 @@ static void dpp_handle_config_response_frame(const struct mmpdu_header *frame, struct dpp_configuration *config; struct station *station = station_find(netdev_get_ifindex(dpp->netdev)); struct network *network = NULL; - struct scan_bss *bss = NULL; char ssid[33]; if (dpp->state != DPP_STATE_CONFIGURING) @@ -819,8 +796,6 @@ static void dpp_handle_config_response_frame(const struct mmpdu_header *frame, ssid[config->ssid_len] = '\0'; network = station_network_find(station, ssid, SECURITY_PSK); - if (network) - bss = network_bss_select(network, true); } dpp_write_config(config, network); @@ -830,16 +805,9 @@ static void dpp_handle_config_response_frame(const struct mmpdu_header *frame, offchannel_cancel(dpp->wdev_id, dpp->offchannel_id); - if (network && bss) - __station_connect_network(station, network, bss); - else if (station) { - dpp->connect_scan_id = scan_active(dpp->wdev_id, NULL, 0, - dpp_scan_triggered, - dpp_scan_results, dpp, - dpp_scan_destroy); - if (dpp->connect_scan_id) - return; - } + dpp->state = DPP_STATE_SUCCESS; + + station_set_autoconnect(station, true); dpp_reset(dpp); } @@ -1579,6 +1547,7 @@ static void dpp_offchannel_timeout(int error, void *user_data) case DPP_STATE_PRESENCE: break; case DPP_STATE_NOTHING: + case DPP_STATE_SUCCESS: /* Protocol already terminated */ return; case DPP_STATE_AUTHENTICATING: @@ -2508,6 +2477,15 @@ static struct l_dbus_message *dpp_dbus_start_enrollee(struct l_dbus *dbus, dpp->state = DPP_STATE_PRESENCE; dpp->role = DPP_CAPABILITY_ENROLLEE; + /* + * If the DPP fails its probably best to continue with periodic scans + * just in case there is an available network. + */ + if (station) { + dpp->station_autoconnecting = station_get_autoconnect(station); + station_set_autoconnect(station, false); + } + l_ecdh_generate_key_pair(dpp->curve, &dpp->proto_private, &dpp->own_proto_public); From patchwork Thu Oct 26 20:26:45 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Prestwood X-Patchwork-Id: 13437858 Received: from mail-qk1-f179.google.com (mail-qk1-f179.google.com [209.85.222.179]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4EDE03CCFD for ; Thu, 26 Oct 2023 20:27:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="SkeYEIK1" Received: by mail-qk1-f179.google.com with SMTP id af79cd13be357-777719639adso98217585a.3 for ; Thu, 26 Oct 2023 13:27:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1698352030; x=1698956830; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=kaCMVsCA3Skgdtdb5dzbkLzo703uc9kuRvL75iohSOg=; b=SkeYEIK1T24ub4gi8TdY970yr4Fyk9gLy4qn9vY+mIDrU5tpJmq5WcgB3X/8bmCHdM 3Q6ZJ9fsarMGCrTu5ngcO8CuS0V8RbwiFFCTsITKXKERdY7/c0fV/OWvgWA5hldw9qoD 91dSneXwf9EPJ9kPwuhe3ppwFuyaUxBqJnEVk+UEFwlr5BncIa+BU6qBoNyP03sRFKte VLHfNwt22q//9+F1sfba9F0gVcZJEz5q2jD3S+u66Aizd14UpF20WWkQNkOVrakLEj4k dqWzNB2oMRkhEbsjV355NP9wg6+EJlYeQhOBON3H/kGRMLJ7Y9QrMWGwKYmXPQITDdNH PGRg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698352030; x=1698956830; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=kaCMVsCA3Skgdtdb5dzbkLzo703uc9kuRvL75iohSOg=; b=suRf3MME3AhgfQ7+vnlDuaPkAnHF5RqzwxLk1s7RA34jvbUqVluXM4s3ynmSugjqVn rb/IPWWVwxhT+Vl/+46nvv3eUSmTG+HxvXihfKYUlJUtENwxT/A9ZNaxnCTjcAuozQf6 lhUtjYVHpvtA0U0PliiK9x1pY+mf/5l6A/iSryIGd+QovsggzhexA8A0j2G2SINY4dX0 xqwqiM/8fZxi6maMHjPmA75v1vpuKxiZ4xCHqv9nuZ7URnve7L2Ne7S+wFOMWRb2/GE6 bOS2yQ2KTsSVK6XIiSRc/tqiT0w3G8kyAqiyji//EUSupkAXrZlhKychBVZ2WajUJ3Ki KGAQ== X-Gm-Message-State: AOJu0Yy3htxPsmU4wKXNAsRUgCKSIpP0D976+zTrwLhXSS2Orw7/Orn6 /UTNrHkZo2jwbknnsY6DyHqacRhWm8A= X-Google-Smtp-Source: AGHT+IEvjnZWO8RLpSpXter1eF2jGBp7I7nOCNxZO7cGU5+Nt1zi2yxmLmAEu52tIHBVdioHTXBcEw== X-Received: by 2002:a05:620a:1373:b0:778:912b:6014 with SMTP id d19-20020a05620a137300b00778912b6014mr410939qkl.37.1698352030132; Thu, 26 Oct 2023 13:27:10 -0700 (PDT) Received: from LOCLAP699.rst-02.locus (50-78-19-50-static.hfc.comcastbusiness.net. [50.78.19.50]) by smtp.gmail.com with ESMTPSA id r4-20020a05620a298400b007742c2ad7dfsm7303qkp.73.2023.10.26.13.27.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 26 Oct 2023 13:27:09 -0700 (PDT) From: James Prestwood To: iwd@lists.linux.dev Cc: James Prestwood Subject: [PATCH v2 03/15] dpp: check configurator role in config request frame Date: Thu, 26 Oct 2023 13:26:45 -0700 Message-Id: <20231026202657.183591-4-prestwoj@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231026202657.183591-1-prestwoj@gmail.com> References: <20231026202657.183591-1-prestwoj@gmail.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 We shouldn't ever get this frame as an enrollee, so disregard --- src/dpp.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/dpp.c b/src/dpp.c index 23b17d01..edf5b797 100644 --- a/src/dpp.c +++ b/src/dpp.c @@ -914,6 +914,9 @@ static void dpp_handle_config_request_frame(const struct mmpdu_header *frame, return; } + if (dpp->role != DPP_CAPABILITY_CONFIGURATOR) + return; + if (memcmp(dpp->peer_addr, frame->address_2, 6)) { l_debug("Configuration request not from authenticated peer"); return; From patchwork Thu Oct 26 20:26:46 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Prestwood X-Patchwork-Id: 13437859 Received: from mail-qk1-f180.google.com (mail-qk1-f180.google.com [209.85.222.180]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 30101156CE for ; Thu, 26 Oct 2023 20:27:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="QRvz45wN" Received: by mail-qk1-f180.google.com with SMTP id af79cd13be357-778ac9c898dso95148185a.0 for ; Thu, 26 Oct 2023 13:27:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1698352032; x=1698956832; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=vspZ3063PT8rLCFF2eW8T+0lR8ve4BKekxoj2RMmcdU=; b=QRvz45wN8S4fZ1FxdgqtafrF7CdkD66FWdG6Sdi/3uSTdsTr0YRJUKv1q8+cFghBfM MPTcfpaqA8mkuo4kKhlfUnzQbqpesFOKC02s+thSdlhYgBykXn+gECIFNmDupOAjP7u6 M9viF+a7t1vc2QUHmeLX15Chd6aW9TUO24WwK+f7abkxNEoGYU9BzTzSc9AiVuz2huQo q0Zk4nkuN1kBeVof05ilc09Axv+fP0eggLCtmNHVWibVJi+1BUyZCmqVXUBzo64kkHAj KH3RGrZnhFNoBswcDlp7sUbN/6NcQ+ry3AES9cMkWAeTU8OGhMOmgoWOgsazcWPW777K h0Fg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698352032; x=1698956832; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=vspZ3063PT8rLCFF2eW8T+0lR8ve4BKekxoj2RMmcdU=; b=H8DPGE72PeBHHdZTTtlzYXYN0swg7C2gbyYVZj6bFqx3g1OqLxnq8yCYwIS65OMYu3 OSXMHoDfc8v8OztDGzHXQlLb+4wezvpey/rKmM7VgOmrethsrRxjMw8VEf5U5syZgoxm HggXK9XMk25kwiExI54iS3uGXwbITyvbQMJNHhUqH4hxxI49K5+V/JEkbgiP9QH8ODiR Tp5KSKqcI7wDl0OGL8rzgSEVfXqg6VlynFn+qjGBLdbTayhFwdyGAtoUAZEufKuinDUe eCBFniYu1ogkBBEpIV2+aXz4Dkt51wHk+iTgbgVJJLpAoxyy+avTlJOVQ9AFFU7IICZz Jy/Q== X-Gm-Message-State: AOJu0YxM+m3xFpwugca149AXNT5X8cNaOrKttN4Tedo/gPIF/pcVJyJl zNNJz34BnuxkjeC0Jt7IRpSL82oEnTo= X-Google-Smtp-Source: AGHT+IGalYTiBJfNrfYmplahbDOR0h0VLo4KW1odU7zT6b+NCTl2WtI37zhf+DiC8JDAbaoChtddMQ== X-Received: by 2002:a05:620a:2949:b0:76f:1318:d7d1 with SMTP id n9-20020a05620a294900b0076f1318d7d1mr379628qkp.75.1698352031927; Thu, 26 Oct 2023 13:27:11 -0700 (PDT) Received: from LOCLAP699.rst-02.locus (50-78-19-50-static.hfc.comcastbusiness.net. [50.78.19.50]) by smtp.gmail.com with ESMTPSA id r4-20020a05620a298400b007742c2ad7dfsm7303qkp.73.2023.10.26.13.27.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 26 Oct 2023 13:27:11 -0700 (PDT) From: James Prestwood To: iwd@lists.linux.dev Cc: James Prestwood Subject: [PATCH v2 04/15] dpp: make the protocol timeout more flexible Date: Thu, 26 Oct 2023 13:26:46 -0700 Message-Id: <20231026202657.183591-5-prestwoj@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231026202657.183591-1-prestwoj@gmail.com> References: <20231026202657.183591-1-prestwoj@gmail.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Include a specific timeout value so different protocols can specify different timeouts. For example once the authentication timeout should not take very long (even 10 seconds seems excessive) but adding PKEX may warrant longer timeouts. For example discovering a configurator IWD may want to wait several minutes before ending the discovery. Similarly running PKEX as a configurator we should put a hard limit on the time, but again minutes rather than 10 seconds. --- src/dpp.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/dpp.c b/src/dpp.c index edf5b797..dff0ecaf 100644 --- a/src/dpp.c +++ b/src/dpp.c @@ -56,6 +56,7 @@ #define DPP_FRAME_MAX_RETRIES 5 #define DPP_FRAME_RETRY_TIMEOUT 1 +#define DPP_AUTH_PROTO_TIMEOUT 10 static uint32_t netdev_watch; static struct l_genl_family *nl80211; @@ -488,12 +489,12 @@ static void dpp_protocol_timeout(struct l_timeout *timeout, void *user_data) dpp_reset(dpp); } -static void dpp_reset_protocol_timer(struct dpp_sm *dpp) +static void dpp_reset_protocol_timer(struct dpp_sm *dpp, uint32_t time) { if (dpp->timeout) - l_timeout_modify(dpp->timeout, 10); + l_timeout_modify(dpp->timeout, time); else - dpp->timeout = l_timeout_create(10, dpp_protocol_timeout, + dpp->timeout = l_timeout_create(time, dpp_protocol_timeout, dpp, NULL); } @@ -1316,7 +1317,7 @@ static void authenticate_confirm(struct dpp_sm *dpp, const uint8_t *from, l_debug("Authentication successful"); - dpp_reset_protocol_timer(dpp); + dpp_reset_protocol_timer(dpp, DPP_AUTH_PROTO_TIMEOUT); if (dpp->role == DPP_CAPABILITY_ENROLLEE) dpp_configuration_start(dpp, from); @@ -1790,7 +1791,7 @@ static void authenticate_request(struct dpp_sm *dpp, const uint8_t *from, memcpy(dpp->peer_addr, from, 6); dpp->state = DPP_STATE_AUTHENTICATING; - dpp_reset_protocol_timer(dpp); + dpp_reset_protocol_timer(dpp, DPP_AUTH_PROTO_TIMEOUT); /* Don't send if the frequency is changing */ if (!dpp->new_freq) From patchwork Thu Oct 26 20:26:47 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Prestwood X-Patchwork-Id: 13437860 Received: from mail-qk1-f176.google.com (mail-qk1-f176.google.com [209.85.222.176]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9F7973CCFD for ; Thu, 26 Oct 2023 20:27:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="BSw+zGLK" Received: by mail-qk1-f176.google.com with SMTP id af79cd13be357-7788fb06997so102995685a.0 for ; Thu, 26 Oct 2023 13:27:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1698352033; x=1698956833; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=FSvt6ZDaBum2UHDFAGyA7QBLUBxP0Owt66+RsftU13Q=; b=BSw+zGLKhbrCYxGHCz2F5UYHRvVXu6QpWXQO04lsUOQ7GgaDBrvypl6N3uOaeP7Sqo pHt3spm81egbkBzZ6Hvu0fXzteTiuV2KDdsrztDV5x1EvHEYBPkb0fBGphuPFALFExmB dFYPuEx4l6CZxzBJZX7WYsRlc0BSiLp8ZNWnsR9Z+OTvjeOgoTCOJ5LPyNCCDchLupZd GRDAkMlbuynVymi01ByxO15MFxegdEtYVFnhnzmolUajppCpnOS5bJIaIC6zGwUCFtCq 2V+e6GEEyVqb19SgGBEfPkp1KAIT+Ud5epEO6+Gy4FkyAZUrrf5zzZpYbU3VpDru8feF //4w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698352033; x=1698956833; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=FSvt6ZDaBum2UHDFAGyA7QBLUBxP0Owt66+RsftU13Q=; b=DaBjQv/Ie66HNphIvxgKg+3IfgSBDljfttzYybtsYqth2viq3WcZgSZY4fBJgpZAQw O7JbIqxkvoF+YWyn+QX9yZAjDevsSMoaVRSLPy21/sNddSVh4Q6DBMCXPxB0u7H31NFJ noNTogSDHrhEiEwe6qaMBFMQAbZp3VC2gF0f9/Zns+qsGjpC2gYSC8Hiwf6ad29pvo2S bvafwIZxsuzXdndbsr0XVMNByqBSW7R4+0HxtXBbVNNERIFME5le2oeo8vHHyLMsoB5p CLWuauIZk7QTlqXT2xDRiDf4pQ8KLPkyc2vD/8vU0hglglXI2iTLI9J6AHwww+arSzRB vs5Q== X-Gm-Message-State: AOJu0YwK7meyRruNuQ3WgSOHsOFx1Plv2q3sCb98d4o9DBe9zlDt/h2+ xfzEG5yLyYGKCqJsn3/eYPVYE2pxxcI= X-Google-Smtp-Source: AGHT+IGwDTogpnYgqDzXwi99oP30BnZJw7CjmRsDsDz4Mi3U3tVA0qO5T1rjoQUtFsLZ7e047IqEaw== X-Received: by 2002:a05:620a:2890:b0:774:17f5:471e with SMTP id j16-20020a05620a289000b0077417f5471emr486786qkp.46.1698352033346; Thu, 26 Oct 2023 13:27:13 -0700 (PDT) Received: from LOCLAP699.rst-02.locus (50-78-19-50-static.hfc.comcastbusiness.net. [50.78.19.50]) by smtp.gmail.com with ESMTPSA id r4-20020a05620a298400b007742c2ad7dfsm7303qkp.73.2023.10.26.13.27.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 26 Oct 2023 13:27:13 -0700 (PDT) From: James Prestwood To: iwd@lists.linux.dev Cc: James Prestwood Subject: [PATCH v2 05/15] dpp: fix config request header check Date: Thu, 26 Oct 2023 13:26:47 -0700 Message-Id: <20231026202657.183591-6-prestwoj@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231026202657.183591-1-prestwoj@gmail.com> References: <20231026202657.183591-1-prestwoj@gmail.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The check for the header was incorrect according to the spec. Table 58 indicates that the "Query Response Info" should be set to 0x00 for the configuration request. The frame handler was expecting 0x7f which is the value for the config response frame. Unfortunately wpa_supplicant also gets this wrong and uses 0x7f in all cases which is likely why this value was set incorrectly in IWD. The issue is that IWD's config request is correct which means IWD<->IWD configuration is broken. (and wpa_supplicant as a configurator likely doesn't validate the config request). Fix this by checking both 0x7f and 0x00 to handle both supplicants. --- src/dpp.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/dpp.c b/src/dpp.c index dff0ecaf..6fd37272 100644 --- a/src/dpp.c +++ b/src/dpp.c @@ -887,6 +887,21 @@ static void dpp_send_config_response(struct dpp_sm *dpp, uint8_t status) dpp_send_frame(dpp, iov, 2, dpp->current_freq); } +static bool dpp_check_config_header(const uint8_t *ptr) +{ + /* + * Table 58. General Format of DPP Configuration Request frame + * + * Unfortunately wpa_supplicant hard codes 0x7f as the Query Response + * Info so we need to handle both cases. + */ + return ptr[0] != IE_TYPE_ADVERTISEMENT_PROTOCOL || + ptr[1] != 0x08 || + (ptr[2] != 0x7f || ptr[2] != 0x00) || + ptr[3] != IE_TYPE_VENDOR_SPECIFIC || + ptr[4] != 5; +} + static void dpp_handle_config_request_frame(const struct mmpdu_header *frame, const void *body, size_t body_len, int rssi, void *user_data) @@ -904,8 +919,6 @@ static void dpp_handle_config_request_frame(const struct mmpdu_header *frame, const uint8_t *e_nonce = NULL; size_t wrapped_len = 0; _auto_(l_free) uint8_t *unwrapped = NULL; - uint8_t hdr_check[] = { IE_TYPE_ADVERTISEMENT_PROTOCOL, 0x08, 0x7f, - IE_TYPE_VENDOR_SPECIFIC, 5 }; struct json_iter jsiter; _auto_(l_free) char *tech = NULL; _auto_(l_free) char *role = NULL; @@ -932,10 +945,10 @@ static void dpp_handle_config_request_frame(const struct mmpdu_header *frame, dpp->diag_token = *ptr++; - if (memcmp(ptr, hdr_check, sizeof(hdr_check))) + if (!dpp_check_config_header(ptr)) return; - ptr += sizeof(hdr_check); + ptr += 5; if (memcmp(ptr, wifi_alliance_oui, sizeof(wifi_alliance_oui))) return; From patchwork Thu Oct 26 20:26:48 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Prestwood X-Patchwork-Id: 13437861 Received: from mail-qk1-f180.google.com (mail-qk1-f180.google.com [209.85.222.180]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E9807156CE for ; Thu, 26 Oct 2023 20:27:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="i/HAhwIt" Received: by mail-qk1-f180.google.com with SMTP id af79cd13be357-779fb118fe4so96012685a.2 for ; Thu, 26 Oct 2023 13:27:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1698352035; x=1698956835; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=hdxpq72IgTIrQSGPnwcZL28kW20N6UFvKjYBlPkvscE=; b=i/HAhwItUqEjaAXpIkUYT/0XvkYkOLPN7b59yhgacLS/cQul/iWC0k55C8nBbJF2fB fr+dc0F3D4zIaGVY9Z3lyngocyyIC6jbRq/yGfC/EKQjjfrBxLJFP5tkXaSwyxfyCC1P 1JcXrpmgYTPmGzewENs01O8tyB5EvEHorrMqeAtlJy8DkIYciG4U7DjDNd4UF4UdtKW/ t+1E36DEUUqJG0Nb2c+AYULV5IQtiqg8rsUrMCyhJR+M2vHxK2y/MHQojskmqI5cQ0rW ingVR2kp676qupN6EPsoxNFmWVYJFjulm5RTyQQN6mxK4YhH5YcACZA6wwHNUmHHrHqy rL8Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698352035; x=1698956835; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=hdxpq72IgTIrQSGPnwcZL28kW20N6UFvKjYBlPkvscE=; b=Rdp7msSSRbCS+oD9MHiJO5uf7C2vpHETC4Q/JsNUgWCNl/aovR0NPXCjfy46G/OxeE iQxwjOKfkrYLwYwM717UfYiUnakL/vya8nGK2QO1RLACFZoEN7DCi1zfNojSaoXySgnx UMgddfisHneMAo9FSNpI+3H5Aivsp5wzmeiedK+iSXo9z5oRL8QCAL7VeqxNFZO0QdO3 uObbEKUBNIgfXkZgmJR6AtDTc+qJeXewvzE8v7ygxKYTqMic7PIfKBtU3/WsWUamdKaT s7Ur6+2efwvx2LlRP++WX9xK1jq1lpVtDE/TmbiTBtdsKQobUGzvdZNv2KPEJUuk9DGj 3SDg== X-Gm-Message-State: AOJu0Yzr8c17M4sbNUkD4UP8Y66ihl2+GH2xpr6R071q9bw7pH31iIQo MjEX/cOJZ9iLaO2j9MaWbxZKCgYOQX4= X-Google-Smtp-Source: AGHT+IGEHgzfPyCULtOYzS9r+ANEAgwECvH2b4U3a5av0U2Ms7OvWkVls1urh4j6HJtyZpISqdGQEA== X-Received: by 2002:a05:620a:d8a:b0:777:fec:5736 with SMTP id q10-20020a05620a0d8a00b007770fec5736mr438887qkl.49.1698352034791; Thu, 26 Oct 2023 13:27:14 -0700 (PDT) Received: from LOCLAP699.rst-02.locus (50-78-19-50-static.hfc.comcastbusiness.net. [50.78.19.50]) by smtp.gmail.com with ESMTPSA id r4-20020a05620a298400b007742c2ad7dfsm7303qkp.73.2023.10.26.13.27.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 26 Oct 2023 13:27:14 -0700 (PDT) From: James Prestwood To: iwd@lists.linux.dev Cc: James Prestwood Subject: [PATCH v2 06/15] dpp-util: add crypto for PKEX Date: Thu, 26 Oct 2023 13:26:48 -0700 Message-Id: <20231026202657.183591-7-prestwoj@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231026202657.183591-1-prestwoj@gmail.com> References: <20231026202657.183591-1-prestwoj@gmail.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 --- src/dpp-util.c | 275 +++++++++++++++++++++++++++++++++++++++++++++++++ src/dpp-util.h | 35 +++++++ 2 files changed, 310 insertions(+) diff --git a/src/dpp-util.c b/src/dpp-util.c index 0406a4dc..cadc6437 100644 --- a/src/dpp-util.c +++ b/src/dpp-util.c @@ -39,6 +39,33 @@ #include "ell/asn1-private.h" #include "src/ie.h" +/* WFA Easy Connect v3.0 C.1 Role-specific Elements for NIST p256 */ +static const uint8_t dpp_pkex_initiator_p256[64] = { + /* X */ + 0x56, 0x26, 0x12, 0xcf, 0x36, 0x48, 0xfe, 0x0b, + 0x07, 0x04, 0xbb, 0x12, 0x22, 0x50, 0xb2, 0x54, + 0xb1, 0x94, 0x64, 0x7e, 0x54, 0xce, 0x08, 0x07, + 0x2e, 0xec, 0xca, 0x74, 0x5b, 0x61, 0x2d, 0x25, + /* Y */ + 0x3e, 0x44, 0xc7, 0xc9, 0x8c, 0x1c, 0xa1, 0x0b, + 0x20, 0x09, 0x93, 0xb2, 0xfd, 0xe5, 0x69, 0xdc, + 0x75, 0xbc, 0xad, 0x33, 0xc1, 0xe7, 0xc6, 0x45, + 0x4d, 0x10, 0x1e, 0x6a, 0x3d, 0x84, 0x3c, 0xa4 +}; + +static const uint8_t dpp_pkex_responder_p256[64] = { + /* X */ + 0x1e, 0xa4, 0x8a, 0xb1, 0xa4, 0xe8, 0x42, 0x39, + 0xad, 0x73, 0x07, 0xf2, 0x34, 0xdf, 0x57, 0x4f, + 0xc0, 0x9d, 0x54, 0xbe, 0x36, 0x1b, 0x31, 0x0f, + 0x59, 0x91, 0x52, 0x33, 0xac, 0x19, 0x9d, 0x76, + /* Y */ + 0xd9, 0xfb, 0xf6, 0xb9, 0xf5, 0xfa, 0xdf, 0x19, + 0x58, 0xd8, 0x3e, 0xc9, 0x89, 0x7a, 0x35, 0xc1, + 0xbd, 0xe9, 0x0b, 0x77, 0x7a, 0xcb, 0x91, 0x2a, + 0xe8, 0x21, 0x3f, 0x47, 0x52, 0x02, 0x4d, 0x67 +}; + static void append_freqs(struct l_string *uri, const uint32_t *freqs, size_t len) { @@ -1134,3 +1161,251 @@ void dpp_free_uri_info(struct dpp_uri_info *info) l_free(info); } + +/* + * 6.3.4 DPP Authentication Confirm + * + * L = bI * (BR + PR) + */ +struct l_ecc_point *dpp_derive_li(const struct l_ecc_point *boot_public, + const struct l_ecc_point *proto_public, + const struct l_ecc_scalar *boot_private) +{ + const struct l_ecc_curve *curve = l_ecc_point_get_curve(boot_public); + struct l_ecc_point *ret = l_ecc_point_new(curve); + + l_ecc_point_add(ret, boot_public, proto_public); + l_ecc_point_multiply(ret, boot_private, ret); + + return ret; +} + +/* + * 6.3.3 DPP Authentication Response + * + * L = ((bR + pR) modulo q) * BI + */ +struct l_ecc_point *dpp_derive_lr(const struct l_ecc_scalar *boot_private, + const struct l_ecc_scalar *proto_private, + const struct l_ecc_point *peer_public) +{ + const struct l_ecc_curve *curve = l_ecc_point_get_curve(peer_public); + _auto_(l_ecc_scalar_free) struct l_ecc_scalar *order = + l_ecc_curve_get_order(curve); + _auto_(l_ecc_scalar_free) struct l_ecc_scalar *sum = + l_ecc_scalar_new(curve, NULL, 0); + _auto_(l_ecc_point_free) struct l_ecc_point *ret = + l_ecc_point_new(curve); + + if (!l_ecc_scalar_add(sum, boot_private, proto_private, order)) + return NULL; + + if (!l_ecc_point_multiply(ret, sum, peer_public)) + return NULL; + + return l_steal_ptr(ret); +} + + +static struct l_ecc_point *dpp_derive_q(const struct l_ecc_curve *curve, + const uint8_t *p_data, + const char *key, + const char *identifier, + const uint8_t *mac) +{ + _auto_(l_ecc_scalar_free) struct l_ecc_scalar *scalar = NULL; + _auto_(l_ecc_point_free) struct l_ecc_point *ret = NULL; + uint8_t hash[L_ECC_SCALAR_MAX_BYTES]; + unsigned int bytes = l_ecc_curve_get_scalar_bytes(curve); + enum l_checksum_type type = dpp_sha_from_key_len(bytes); + _auto_(l_ecc_point_free) struct l_ecc_point *p = NULL; + struct l_checksum *sha = l_checksum_new(type); + + /* + * "If the Initiator indicates PKEX with a Protocol Version of 1, + * MAC-Initiator shall be the MAC address of the Initiator and the + * Protocol Version shall not be present. Otherwise, MAC-Initiator is + * not present" + * + * (This goes for MAC-Responder as well) + */ + if (mac) + l_checksum_update(sha, mac, 6); + + if (identifier) + l_checksum_update(sha, identifier, strlen(identifier)); + + l_checksum_update(sha, key, strlen(key)); + l_checksum_get_digest(sha, hash, bytes); + l_checksum_free(sha); + + /* Unlikely but can happen */ + scalar = l_ecc_scalar_new(curve, hash, bytes); + if (!scalar) + return NULL; + + p = l_ecc_point_from_data(curve, L_ECC_POINT_TYPE_FULL, + p_data, bytes * 2); + if (!p) + return NULL; + + ret = l_ecc_point_new(curve); + + if (!l_ecc_point_multiply(ret, scalar, p)) + return NULL; + + return l_steal_ptr(ret); +} + +/* + * 5.6.2 PKEX Exchange Phase + * + * Qi = H([MAC-Initiator |] [identifier | ] code) * Pi + */ +struct l_ecc_point *dpp_derive_qi(const struct l_ecc_curve *curve, + const char *key, + const char *identifier, + const uint8_t *mac_initiator) +{ + return dpp_derive_q(curve, dpp_pkex_initiator_p256, key, identifier, + mac_initiator); +} + +/* + * 5.6.2 PKEX Exchange Phase + * + * Qr = H([MAC-Responder |] [identifier | ] code) * Pr + */ +struct l_ecc_point *dpp_derive_qr(const struct l_ecc_curve *curve, + const char *key, + const char *identifier, + const uint8_t *mac_responder) +{ + return dpp_derive_q(curve, dpp_pkex_responder_p256, key, identifier, + mac_responder); +} + +/* + * 5.6.2 PKEX Exchange Phase + * + * z = HKDF(<>, info | M.x | N.x | code, K.x) + */ +bool dpp_derive_z(const uint8_t *mac_i, const uint8_t *mac_r, + const struct l_ecc_point *n, + const struct l_ecc_point *m, + const struct l_ecc_point *k, + const char *key, + const char *identifier, + void *z_out, size_t *z_len) +{ + const struct l_ecc_curve *curve = l_ecc_point_get_curve(n); + size_t bytes = l_ecc_curve_get_scalar_bytes(curve); + enum l_checksum_type sha = dpp_sha_from_key_len(bytes); + uint8_t k_x[L_ECC_SCALAR_MAX_BYTES]; + uint8_t m_x[L_ECC_SCALAR_MAX_BYTES]; + uint8_t n_x[L_ECC_SCALAR_MAX_BYTES]; + uint8_t prk[L_ECC_SCALAR_MAX_BYTES]; + + l_ecc_point_get_x(k, k_x, sizeof(k_x)); + l_ecc_point_get_x(m, m_x, sizeof(m_x)); + l_ecc_point_get_x(n, n_x, sizeof(n_x)); + + hkdf_extract(sha, NULL, 0, 1, prk, k_x, bytes); + + /* HKDF-Extract (since it doesn't take non-string arguments)*/ + prf_plus(sha, prk, bytes, z_out, bytes, 5, mac_i, 6, mac_r, 6, m_x, + bytes, n_x, bytes, key, strlen(key)); + + *z_len = bytes; + + return true; +} + +/* + * 5.6.3 PKEX Commit-Reveal Phase + * + * Initiator derivation: + * u = HMAC(J.x, [MAC-Initiator |] A.x | Y'.x | X.x ) + * + * Responder derivation: + * u' = HMAC(J'.x, [MAC-Initiator |] A'.x | Y.x | X'.x) + */ +bool dpp_derive_u(const struct l_ecc_point *j, + const uint8_t *mac_i, + const struct l_ecc_point *a, + const struct l_ecc_point *y, + const struct l_ecc_point *x, + void *u_out, size_t *u_len) +{ + const struct l_ecc_curve *curve = l_ecc_point_get_curve(y); + uint8_t j_x[L_ECC_SCALAR_MAX_BYTES]; + uint8_t a_x[L_ECC_SCALAR_MAX_BYTES]; + uint8_t y_x[L_ECC_SCALAR_MAX_BYTES]; + uint8_t x_x[L_ECC_SCALAR_MAX_BYTES]; + size_t bytes = l_ecc_curve_get_scalar_bytes(curve); + enum l_checksum_type sha = dpp_sha_from_key_len(bytes); + struct l_checksum *hmac; + + l_ecc_point_get_x(j, j_x, bytes); + l_ecc_point_get_x(a, a_x, bytes); + l_ecc_point_get_x(y, y_x, bytes); + l_ecc_point_get_x(x, x_x, bytes); + + /* u = HMAC(J.x, MAC-Initiator | A.x | Y'.x | X.x)*/ + hmac = l_checksum_new_hmac(sha, j_x, bytes); + l_checksum_update(hmac, mac_i, 6); + l_checksum_update(hmac, a_x, bytes); + l_checksum_update(hmac, y_x, bytes); + l_checksum_update(hmac, x_x, bytes); + l_checksum_get_digest(hmac, u_out, bytes); + l_checksum_free(hmac); + + *u_len = bytes; + + return true; +} + +/* + * 5.6.3 PKEX Commit-Reveal Phase + * + * Initiator derivation: + * v = HMAC(L.x, [MAC-Responder |] B.x | X'.x |Y.x ) + * + * Responder derivation: + * v' = HMAC(L.x, [MAC-Responder |] B'.x | X.x | Y'.x ) + */ +bool dpp_derive_v(const struct l_ecc_point *l, const uint8_t *mac, + const struct l_ecc_point *b, + const struct l_ecc_point *x, + const struct l_ecc_point *y, + void *v_out, size_t *v_len) +{ + const struct l_ecc_curve *curve = l_ecc_point_get_curve(l); + uint8_t l_x[L_ECC_SCALAR_MAX_BYTES]; + uint8_t b_x[L_ECC_SCALAR_MAX_BYTES]; + uint8_t x_x[L_ECC_SCALAR_MAX_BYTES]; + uint8_t y_x[L_ECC_SCALAR_MAX_BYTES]; + size_t bytes = l_ecc_curve_get_scalar_bytes(curve); + enum l_checksum_type sha = dpp_sha_from_key_len(bytes); + struct l_checksum *hmac; + + l_ecc_point_get_x(l, l_x, sizeof(l_x)); + l_ecc_point_get_x(b, b_x, sizeof(b_x)); + l_ecc_point_get_x(x, x_x, sizeof(x_x)); + l_ecc_point_get_x(y, y_x, sizeof(y_x)); + + hmac = l_checksum_new_hmac(sha, l_x, bytes); + + if (mac) + l_checksum_update(hmac, mac, 6); + + l_checksum_update(hmac, b_x, bytes); + l_checksum_update(hmac, x_x, bytes); + l_checksum_update(hmac, y_x, bytes); + l_checksum_get_digest(hmac, v_out, bytes); + l_checksum_free(hmac); + + *v_len = bytes; + + return true; +} diff --git a/src/dpp-util.h b/src/dpp-util.h index 96711c35..5f9a2ff4 100644 --- a/src/dpp-util.h +++ b/src/dpp-util.h @@ -183,3 +183,38 @@ struct l_ecc_point *dpp_point_from_asn1(const uint8_t *asn1, size_t len); struct dpp_uri_info *dpp_parse_uri(const char *uri); void dpp_free_uri_info(struct dpp_uri_info *info); + +struct l_ecc_point *dpp_derive_qi(const struct l_ecc_curve *curve, + const char *key, + const char *identifier, + const uint8_t *mac_initiator); +struct l_ecc_point *dpp_derive_qr(const struct l_ecc_curve *curve, + const char *key, + const char *identifier, + const uint8_t *mac_responder); +struct l_ecc_point *dpp_derive_li( + const struct l_ecc_point *boot_public, + const struct l_ecc_point *proto_public, + const struct l_ecc_scalar *boot_private); +struct l_ecc_point *dpp_derive_lr( + const struct l_ecc_scalar *boot_private, + const struct l_ecc_scalar *proto_private, + const struct l_ecc_point *peer_public); +bool dpp_derive_z(const uint8_t *mac_i, const uint8_t *mac_r, + const struct l_ecc_point *n, + const struct l_ecc_point *m, + const struct l_ecc_point *k, + const char *key, + const char *identifier, + void *z_out, size_t *z_len); +bool dpp_derive_u(const struct l_ecc_point *j, + const uint8_t *mac_i, + const struct l_ecc_point *a, + const struct l_ecc_point *y, + const struct l_ecc_point *x, + void *u_out, size_t *u_len); +bool dpp_derive_v(const struct l_ecc_point *l, const uint8_t *mac, + const struct l_ecc_point *b, + const struct l_ecc_point *x, + const struct l_ecc_point *y, + void *v_out, size_t *v_len); From patchwork Thu Oct 26 20:26:49 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Prestwood X-Patchwork-Id: 13437862 Received: from mail-qk1-f180.google.com (mail-qk1-f180.google.com [209.85.222.180]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C34003CCFD for ; Thu, 26 Oct 2023 20:27:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ghO8hap4" Received: by mail-qk1-f180.google.com with SMTP id af79cd13be357-777719639adso98222685a.3 for ; Thu, 26 Oct 2023 13:27:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1698352036; x=1698956836; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=JFDJehJE104fBbEMsLTJPktVkCUJULKms/9kwKT+psg=; b=ghO8hap45ygGNewBPmoMVcklUwTcCUq32EeiRkzx0ESwQjenpUpkaucaWYY8nbMzRZ lXOEkLjb/11h0xOOuJUg4bj5yJbecQ9O6PwR81uvXkOiPIUx115vhlOlquW0N9gublNn 9J3BVb5V3IhsSQQihEaKKeYi+difN1LFq2LM8EryhsuJa79Mx7aL9UfFGkWYy0WZVTek /YeMDVto5U7pJY3aRHq5eqoULxWBqK5Z62p3MORuFf9daHwyRxU3M06gg8FzAgoSxvEw Mcp89hzvB0+E7wO1IB2bkFv/5lLnUkbXs0YAj1tyu0jfPhEUwM2o2OIyxoeK51aNP0SU PzoQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698352036; x=1698956836; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=JFDJehJE104fBbEMsLTJPktVkCUJULKms/9kwKT+psg=; b=qSZ0GxXEPIiQZ6XYXX2q1wmKk9JZSQ2kkqDap5/nr3OkYFpjeX4ND0M4G9ppodJHH/ jYo1lz5Qi7ahad7YxlsSRytXqvSNLo7M7JeJGUNHFg37C88ECiwK7CxPJQkkxBFSwmQO xCrskJSuHxtn7ypukWjX9ZfmNdy3zyuX2mQ+dgliDPqppXlfwjamr9fcANAy7Pmvshb1 3qCquepyJ7PWCFl/rKJuFoZEt2U2tUfqVDdtSV1KrXo6u7eHOfMPFONHhz6FHx87Fzyb 0l/j8G5s7yFDnLqx93Yh2LTVCUmVZPcIOv+UP7SZwHKnO6P7pGTtOpsqJwJfkQhNqQob /7KQ== X-Gm-Message-State: AOJu0YyykdnECPwFcUZlTuNitWln87Qp03aOF21DdFGmtUxLR2i/U8st 9MLB0UWljtZKnpsLXFjpq/+GNngEjOM= X-Google-Smtp-Source: AGHT+IHiFDFr089o6dSrAH9yQPiHIxSlO5DwneGUjKpyA98NNSF+WpWQT/GdlbTvnV+jrDU18Aa1MQ== X-Received: by 2002:a05:620a:280a:b0:777:b325:d02d with SMTP id f10-20020a05620a280a00b00777b325d02dmr513221qkp.33.1698352036407; Thu, 26 Oct 2023 13:27:16 -0700 (PDT) Received: from LOCLAP699.rst-02.locus (50-78-19-50-static.hfc.comcastbusiness.net. [50.78.19.50]) by smtp.gmail.com with ESMTPSA id r4-20020a05620a298400b007742c2ad7dfsm7303qkp.73.2023.10.26.13.27.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 26 Oct 2023 13:27:16 -0700 (PDT) From: James Prestwood To: iwd@lists.linux.dev Cc: James Prestwood Subject: [PATCH v2 07/15] dpp: support mutual authentication Date: Thu, 26 Oct 2023 13:26:49 -0700 Message-Id: <20231026202657.183591-8-prestwoj@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231026202657.183591-1-prestwoj@gmail.com> References: <20231026202657.183591-1-prestwoj@gmail.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This will be needed for PKEX support. It requires an additional value, L, be derived and used in some of the hashing functions. --- src/dpp.c | 41 ++++++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/src/dpp.c b/src/dpp.c index 6fd37272..77af5669 100644 --- a/src/dpp.c +++ b/src/dpp.c @@ -151,6 +151,7 @@ struct dpp_sm { bool roc_started : 1; bool channel_switch : 1; bool station_autoconnecting : 1; + bool mutual_auth : 1; }; static bool dpp_get_started(struct l_dbus *dbus, @@ -1153,7 +1154,7 @@ static void dpp_handle_config_result_frame(struct dpp_sm *dpp, static void send_authenticate_response(struct dpp_sm *dpp) { uint8_t hdr[32]; - uint8_t attrs[256]; + uint8_t attrs[512]; uint8_t *ptr = attrs; uint8_t status = DPP_STATUS_OK; uint64_t r_proto_key[L_ECC_MAX_DIGITS * 2]; @@ -1174,6 +1175,9 @@ static void send_authenticate_response(struct dpp_sm *dpp) ptr += dpp_append_attr(ptr, DPP_ATTR_STATUS, &status, 1); ptr += dpp_append_attr(ptr, DPP_ATTR_RESPONDER_BOOT_KEY_HASH, dpp->own_boot_hash, 32); + if (dpp->mutual_auth) + ptr += dpp_append_attr(ptr, DPP_ATTR_INITIATOR_BOOT_KEY_HASH, + dpp->peer_boot_hash, 32); ptr += dpp_append_attr(ptr, DPP_ATTR_RESPONDER_PROTOCOL_KEY, r_proto_key, dpp->key_len * 2); ptr += dpp_append_attr(ptr, DPP_ATTR_PROTOCOL_VERSION, &version, 1); @@ -1227,6 +1231,7 @@ static void authenticate_confirm(struct dpp_sm *dpp, const uint8_t *from, const void *unwrap_key; const void *ad0 = body + 2; const void *ad1 = body + 8; + struct l_ecc_point *bi = NULL; if (dpp->state != DPP_STATE_AUTHENTICATING) return; @@ -1319,9 +1324,12 @@ static void authenticate_confirm(struct dpp_sm *dpp, const uint8_t *from, goto auth_confirm_failed; } + if (dpp->mutual_auth) + bi = dpp->peer_boot_public; + dpp_derive_i_auth(dpp->r_nonce, dpp->i_nonce, dpp->nonce_len, dpp->own_proto_public, dpp->peer_proto_public, - dpp->boot_public, NULL, i_auth_check); + dpp->boot_public, bi, i_auth_check); if (memcmp(i_auth, i_auth_check, i_auth_len)) { l_error("I-Auth did not verify"); @@ -1638,6 +1646,8 @@ static void authenticate_request(struct dpp_sm *dpp, const uint8_t *from, _auto_(l_free) uint8_t *unwrapped = NULL; _auto_(l_ecc_scalar_free) struct l_ecc_scalar *m = NULL; _auto_(l_ecc_scalar_free) struct l_ecc_scalar *n = NULL; + _auto_(l_ecc_point_free) struct l_ecc_point *l = NULL; + struct l_ecc_point *bi = NULL; uint64_t k1[L_ECC_MAX_DIGITS]; const void *ad0 = body + 2; const void *ad1 = body + 8; @@ -1785,6 +1795,12 @@ static void authenticate_request(struct dpp_sm *dpp, const uint8_t *from, memcpy(dpp->i_nonce, i_nonce, i_nonce_len); + if (dpp->mutual_auth) { + l = dpp_derive_lr(dpp->boot_private, dpp->proto_private, + dpp->peer_boot_public); + bi = dpp->peer_boot_public; + } + /* Derive keys k2, ke, and R-Auth for authentication response */ n = dpp_derive_k2(dpp->peer_proto_public, dpp->proto_private, dpp->k2); @@ -1793,12 +1809,12 @@ static void authenticate_request(struct dpp_sm *dpp, const uint8_t *from, l_getrandom(dpp->r_nonce, dpp->nonce_len); - if (!dpp_derive_ke(dpp->i_nonce, dpp->r_nonce, m, n, NULL, dpp->ke)) + if (!dpp_derive_ke(dpp->i_nonce, dpp->r_nonce, m, n, l, dpp->ke)) goto auth_request_failed; if (!dpp_derive_r_auth(dpp->i_nonce, dpp->r_nonce, dpp->nonce_len, dpp->peer_proto_public, dpp->own_proto_public, - NULL, dpp->boot_public, dpp->auth_tag)) + bi, dpp->boot_public, dpp->auth_tag)) goto auth_request_failed; memcpy(dpp->peer_addr, from, 6); @@ -1833,6 +1849,9 @@ static void dpp_send_authenticate_confirm(struct dpp_sm *dpp) ptr += dpp_append_attr(ptr, DPP_ATTR_STATUS, &zero, 1); ptr += dpp_append_attr(ptr, DPP_ATTR_RESPONDER_BOOT_KEY_HASH, dpp->peer_boot_hash, 32); + if (dpp->mutual_auth) + ptr += dpp_append_attr(ptr, DPP_ATTR_INITIATOR_BOOT_KEY_HASH, + dpp->own_boot_hash, 32); ptr += dpp_append_wrapped_data(hdr + 26, 6, attrs, ptr - attrs, ptr, sizeof(attrs), dpp->ke, dpp->key_len, 1, @@ -1865,6 +1884,8 @@ static void authenticate_response(struct dpp_sm *dpp, const uint8_t *from, const void *r_auth = NULL; _auto_(l_ecc_point_free) struct l_ecc_point *r_proto_key = NULL; _auto_(l_ecc_scalar_free) struct l_ecc_scalar *n = NULL; + _auto_(l_ecc_point_free) struct l_ecc_point *l = NULL; + struct l_ecc_point *bi = NULL; const void *ad0 = body + 2; const void *ad1 = body + 8; uint64_t r_auth_derived[L_ECC_MAX_DIGITS]; @@ -1969,7 +1990,13 @@ static void authenticate_response(struct dpp_sm *dpp, const uint8_t *from, return; } - if (!dpp_derive_ke(i_nonce, r_nonce, dpp->m, n, NULL, dpp->ke)) { + if (dpp->mutual_auth) { + l = dpp_derive_li(dpp->peer_boot_public, r_proto_key, + dpp->boot_private); + bi = dpp->boot_public; + } + + if (!dpp_derive_ke(i_nonce, r_nonce, dpp->m, n, l, dpp->ke)) { l_debug("Failed to derive ke"); return; } @@ -2002,7 +2029,7 @@ static void authenticate_response(struct dpp_sm *dpp, const uint8_t *from, } if (!dpp_derive_r_auth(i_nonce, r_nonce, dpp->nonce_len, - dpp->own_proto_public, r_proto_key, NULL, + dpp->own_proto_public, r_proto_key, bi, dpp->peer_boot_public, r_auth_derived)) { l_debug("Failed to derive r_auth"); return; @@ -2015,7 +2042,7 @@ static void authenticate_response(struct dpp_sm *dpp, const uint8_t *from, if (!dpp_derive_i_auth(r_nonce, i_nonce, dpp->nonce_len, r_proto_key, dpp->own_proto_public, - dpp->peer_boot_public, NULL, dpp->auth_tag)) { + dpp->peer_boot_public, bi, dpp->auth_tag)) { l_debug("Could not derive I-Auth"); return; } From patchwork Thu Oct 26 20:26:50 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Prestwood X-Patchwork-Id: 13437863 Received: from mail-qk1-f171.google.com (mail-qk1-f171.google.com [209.85.222.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8B54B156CE for ; Thu, 26 Oct 2023 20:27:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="joUGmER9" Received: by mail-qk1-f171.google.com with SMTP id af79cd13be357-77774120c6eso99328185a.2 for ; Thu, 26 Oct 2023 13:27:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1698352038; x=1698956838; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=dC23NXL4BiynuBhMKrtU8WsgzA1WeIIudl3YwLneMEs=; b=joUGmER9RniOOeKAU899BGSb6PFK3PfRUw4RLxZ7LS+1Bqh67ahq81ZPjqWdXT+/nr al9xuQMPNY/S1wJ0FzYianQ5pfPY5NfitSGw0lAKNNQBVlkJA0JPI0yOnCUqbR+LDons REDa4bITo9EK1z8mAgkezQZJlnA1L9hw638ofrPqOlAo7bTn6ybpRXnZAM+izt1U/fEI HD0PtJsgA0+pNeVNlHkuWFW8yMiLgYTLxRSNrDBoY3urZ+wDi+rw61u3k38dvTCThHt8 /Ejf9kq8E5QyN+O2oIGfRy2v/8i6InO68P3LoiOPBQ2JkUX/79PzEqpER/II5I8+RifJ eStg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698352038; x=1698956838; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=dC23NXL4BiynuBhMKrtU8WsgzA1WeIIudl3YwLneMEs=; b=WeG/4ULoVskBNFopOmuVJlQKURfjM4UbTcPyphfZYaNHNMR90iAsI5eLBTRj7gmlau PG+0tId4V48/k+KT6XoAw81a/ttM6AVKDBY4aTHKAFIVcapHCXnWQrfyK7+1MG+CJ776 4s3ccMH1SJR/kDUCzM3MxwDANE29xzo3hhGdn6uIL/J2wAx2zq8C+5LEvUgi0zZIu7yM Zjr+ECYvlnBdxXHN7gNmR7mPkX3bNh2kTFFVstyexMUbfNxpr+4KamdtPv6cCGo5h9uc y/76HNQinExccK/7ctadxvCpi0QGm4Qw4HGzETeEEswHdvO5//MvvOu8f+0Hd7egx2H1 KDTg== X-Gm-Message-State: AOJu0YywkZ4l0Hi46mkC7DCCn4qbRsu6KfZHGa8y/ZPfLNTbYFgxjyj8 11JUyUL0DK7+mKJYGXv7fHdCEKJSCvU= X-Google-Smtp-Source: AGHT+IHnV6rPGThyrZDpzq6TX87XlB1Ga0FetpKHaD60pqi9gHTWa+33QBjvGEHmmUg2YY5Nn/l6BA== X-Received: by 2002:a05:620a:2890:b0:778:9be8:276c with SMTP id j16-20020a05620a289000b007789be8276cmr491977qkp.37.1698352037960; Thu, 26 Oct 2023 13:27:17 -0700 (PDT) Received: from LOCLAP699.rst-02.locus (50-78-19-50-static.hfc.comcastbusiness.net. [50.78.19.50]) by smtp.gmail.com with ESMTPSA id r4-20020a05620a298400b007742c2ad7dfsm7303qkp.73.2023.10.26.13.27.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 26 Oct 2023 13:27:17 -0700 (PDT) From: James Prestwood To: iwd@lists.linux.dev Cc: James Prestwood Subject: [PATCH v2 08/15] unit: make test-dpp key derivation test more extendable Date: Thu, 26 Oct 2023 13:26:50 -0700 Message-Id: <20231026202657.183591-9-prestwoj@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231026202657.183591-1-prestwoj@gmail.com> References: <20231026202657.183591-1-prestwoj@gmail.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Use a new structure to hold key values so they can be changed for different test vectors while using the same test function. --- unit/test-dpp.c | 104 +++++++++++++++++++++++++++++++----------------- 1 file changed, 68 insertions(+), 36 deletions(-) diff --git a/unit/test-dpp.c b/unit/test-dpp.c index c3f3731f..0cf60f0a 100644 --- a/unit/test-dpp.c +++ b/unit/test-dpp.c @@ -158,29 +158,59 @@ static void test_bad_channels(const void *data) test_uri_parse(&bad_channels[i]); } +struct dpp_test_vector { + /* Initiator values */ + const char *i_proto_public; + const char *i_proto_private; + const char *i_boot_public; + const char *i_boot_private; + const char *i_nonce; + const char *i_auth; + const char *i_asn1; + + /* Responder values */ + const char *r_proto_public; + const char *r_proto_private; + const char *r_boot_public; + const char *r_boot_private; + const char *r_nonce; + const char *r_auth; + const char *r_asn1; + + const char *k1; + const char *k2; + const char *ke; + const char *mx; + const char *nx; +}; + /* * B.2 Test Vectors for DPP Authentication Using P-256 for * Responder-only Authentication */ -const char *i_proto_public_bytes = "50a532ae2a07207276418d2fa630295d45569be425aa634f02014d00a7d1f61a" - "e14f35a5a858bccad90d126c46594c49ef82655e78888e15a32d916ac2172491"; -const char *r_boot_public_bytes = "09c585a91b4df9fd25a045201885c39cc5cfae397ddaeda957dec57fa0e3503f" - "52bf05968198a2f92883e96a386d767579883302dbf292105c90a43694c2fd5c"; -const char *r_boot_private_bytes = "54ce181a98525f217216f59b245f60e9df30ac7f6b26c939418cfc3c42d1afa0"; -const char *r_proto_private_bytes = "f798ed2e19286f6a6efe210b1863badb99af2a14b497634dbfd2a97394fb5aa5"; -const char *r_proto_public_bytes = "5e3fb3576884887f17c3203d8a3a6c2fac722ef0e2201b61ac73bc655c709a90" - "2d4b030669fb9eff8b0a79fa7c1a172ac2a92c626256963f9274dc90682c81e5"; -const char *k1_bytes = "3d832a02ed6d7fc1dc96d2eceab738cf01c0028eb256be33d5a21a720bfcf949"; -const char *k2_bytes = "ca08bdeeef838ddf897a5f01f20bb93dc5a895cb86788ca8c00a7664899bc310"; -const char *ke_bytes = "c8882a8ab30c878467822534138c704ede0ab1e873fe03b601a7908463fec87a"; -const char *mx_bytes = "dde2878117d69745be4f916a2dd14269d783d1d788c603bb8746beabbd1dbbbc"; -const char *nx_bytes = "92118478b75c21c2c59340c842b5bce560a535f60bc37a75fe390d738c58d8e8"; -const char *i_nonce_bytes = "13f4602a16daeb69712263b9c46cba31"; -const char *r_nonce_bytes = "3d0cfb011ca916d796f7029ff0b43393"; -const char *i_auth_bytes = "787d1189b526448d2901e7f6c22775ce514fce52fc886c1e924f2fbb8d97b210"; -const char *r_auth_bytes = "43509ef7137d8c2fbe66d802ae09dedd94d41b8cbfafb4954782014ff4a3f91c"; -const char *r_asn1 = "3039301306072a8648ce3d020106082a8648ce3d0301070322000209c585a91b" - "4df9fd25a045201885c39cc5cfae397ddaeda957dec57fa0e3503f"; +static struct dpp_test_vector responder_only_p256 = { + .i_proto_public = "50a532ae2a07207276418d2fa630295d45569be425aa634f02014d00a7d1f61a" + "e14f35a5a858bccad90d126c46594c49ef82655e78888e15a32d916ac2172491", + .i_nonce = "13f4602a16daeb69712263b9c46cba31", + .i_auth = "787d1189b526448d2901e7f6c22775ce514fce52fc886c1e924f2fbb8d97b210", + + .r_proto_public = "5e3fb3576884887f17c3203d8a3a6c2fac722ef0e2201b61ac73bc655c709a90" + "2d4b030669fb9eff8b0a79fa7c1a172ac2a92c626256963f9274dc90682c81e5", + .r_proto_private = "f798ed2e19286f6a6efe210b1863badb99af2a14b497634dbfd2a97394fb5aa5", + .r_boot_public = "09c585a91b4df9fd25a045201885c39cc5cfae397ddaeda957dec57fa0e3503f" + "52bf05968198a2f92883e96a386d767579883302dbf292105c90a43694c2fd5c", + .r_boot_private = "54ce181a98525f217216f59b245f60e9df30ac7f6b26c939418cfc3c42d1afa0", + .r_nonce = "3d0cfb011ca916d796f7029ff0b43393", + .r_auth = "43509ef7137d8c2fbe66d802ae09dedd94d41b8cbfafb4954782014ff4a3f91c", + .r_asn1 = "3039301306072a8648ce3d020106082a8648ce3d0301070322000209c585a91b" + "4df9fd25a045201885c39cc5cfae397ddaeda957dec57fa0e3503f", + + .k1 = "3d832a02ed6d7fc1dc96d2eceab738cf01c0028eb256be33d5a21a720bfcf949", + .k2 = "ca08bdeeef838ddf897a5f01f20bb93dc5a895cb86788ca8c00a7664899bc310", + .ke = "c8882a8ab30c878467822534138c704ede0ab1e873fe03b601a7908463fec87a", + .mx = "dde2878117d69745be4f916a2dd14269d783d1d788c603bb8746beabbd1dbbbc", + .nx = "92118478b75c21c2c59340c842b5bce560a535f60bc37a75fe390d738c58d8e8", +}; #define HEX2BUF(s, buf, _len) { \ size_t _len_out; \ @@ -198,6 +228,8 @@ const char *r_asn1 = "3039301306072a8648ce3d020106082a8648ce3d0301070322000209c5 static void test_key_derivation(const void *data) { + const struct dpp_test_vector *vector = data; + uint64_t tmp[L_ECC_MAX_DIGITS * 2]; const struct l_ecc_curve *curve = l_ecc_curve_from_ike_group(19); _auto_(l_ecc_point_free) struct l_ecc_point *i_proto_public = NULL; @@ -218,19 +250,19 @@ static void test_key_derivation(const void *data) _auto_(l_free) uint8_t *asn1 = NULL; size_t asn1_len; - HEX2BUF(i_proto_public_bytes, tmp, 64); + HEX2BUF(vector->i_proto_public, tmp, 64); i_proto_public = l_ecc_point_from_data(curve, L_ECC_POINT_TYPE_FULL, tmp, 64); assert(i_proto_public); - HEX2BUF(r_boot_public_bytes, tmp, 64); + HEX2BUF(vector->r_boot_public, tmp, 64); r_boot_public = l_ecc_point_from_data(curve, L_ECC_POINT_TYPE_FULL, tmp, 64); assert(r_boot_public); - HEX2BUF(r_asn1, tmp, sizeof(tmp)); + HEX2BUF(vector->r_asn1, tmp, sizeof(tmp)); asn1 = dpp_point_to_asn1(r_boot_public, &asn1_len); from_asn1 = dpp_point_from_asn1(asn1, asn1_len); @@ -240,47 +272,47 @@ static void test_key_derivation(const void *data) assert(asn1_len == 59); assert(memcmp(tmp, asn1, asn1_len) == 0); - HEX2BUF(r_proto_public_bytes, tmp, 64); + HEX2BUF(vector->r_proto_public, tmp, 64); r_proto_public = l_ecc_point_from_data(curve, L_ECC_POINT_TYPE_FULL, tmp, 64); assert(r_proto_public); - HEX2BUF(r_boot_private_bytes, tmp, 32); + HEX2BUF(vector->r_boot_private, tmp, 32); r_boot_private = l_ecc_scalar_new(curve, tmp, 32); assert(r_boot_private); - HEX2BUF(r_proto_private_bytes, tmp, 32); + HEX2BUF(vector->r_proto_private, tmp, 32); r_proto_private = l_ecc_scalar_new(curve, tmp, 32); assert(r_proto_private); m = dpp_derive_k1(i_proto_public, r_boot_private, k1); assert(m); - CHECK_FROM_STR(k1_bytes, k1, 32); + CHECK_FROM_STR(vector->k1, k1, 32); l_ecc_scalar_get_data(m, tmp, sizeof(tmp)); - CHECK_FROM_STR(mx_bytes, tmp, 32); + CHECK_FROM_STR(vector->mx, tmp, 32); n = dpp_derive_k2(i_proto_public, r_proto_private, k2); assert(n); - CHECK_FROM_STR(k2_bytes, k2, 32); + CHECK_FROM_STR(vector->k2, k2, 32); l_ecc_scalar_get_data(n, tmp, sizeof(tmp)); - CHECK_FROM_STR(nx_bytes, tmp, 32); + CHECK_FROM_STR(vector->nx, tmp, 32); - HEX2BUF(i_nonce_bytes, i_nonce, 16); - HEX2BUF(r_nonce_bytes, r_nonce, 16); + HEX2BUF(vector->i_nonce, i_nonce, 16); + HEX2BUF(vector->r_nonce, r_nonce, 16); dpp_derive_ke(i_nonce, r_nonce, m, n, NULL, ke); - CHECK_FROM_STR(ke_bytes, ke, 32); + CHECK_FROM_STR(vector->ke, ke, 32); dpp_derive_r_auth(i_nonce, r_nonce, 16, i_proto_public, r_proto_public, NULL, r_boot_public, r_auth); - CHECK_FROM_STR(r_auth_bytes, r_auth, 32); + CHECK_FROM_STR(vector->r_auth, r_auth, 32); dpp_derive_i_auth(r_nonce, i_nonce, 16, r_proto_public, i_proto_public, r_boot_public, NULL, i_auth); - CHECK_FROM_STR(i_auth_bytes, i_auth, 32); + CHECK_FROM_STR(vector->i_auth, i_auth, 32); } int main(int argc, char *argv[]) @@ -289,8 +321,8 @@ int main(int argc, char *argv[]) if (l_checksum_is_supported(L_CHECKSUM_SHA256, true) && l_getrandom_is_supported()) - l_test_add("DPP test key derivation", - test_key_derivation, NULL); + l_test_add("DPP test key derivation", test_key_derivation, + &responder_only_p256); l_test_add("DPP URI parse", test_uri_parse, &all_values); l_test_add("DPP URI no type", test_uri_parse, &no_type); From patchwork Thu Oct 26 20:26:51 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Prestwood X-Patchwork-Id: 13437864 Received: from mail-qk1-f179.google.com (mail-qk1-f179.google.com [209.85.222.179]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0534E3CCFD for ; Thu, 26 Oct 2023 20:27:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="FF6xBtu6" Received: by mail-qk1-f179.google.com with SMTP id af79cd13be357-778711ee748so104352385a.2 for ; Thu, 26 Oct 2023 13:27:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1698352040; x=1698956840; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=QkDBubNt3gstw368lHcAZnlIM74s0njBq318BQ7+2R0=; b=FF6xBtu6s2EGP0CStuf1N+q+g0WJJCh9jIIg6jetqXONT/ZMR6CTnOMxCJT+JKAzyQ ChNI9/nOmXpUcp7ejv37d4506f555rEjlFpS31x+cd/+oYCQTfjCZwPpHSezq1u7/TEv v2pKZ35oAdFXyI+Q4lyc2utdyZMSPfsiWypMLk6QlF/M907JAP1bTjxB8WNIsOvGa4Wt ZSjacQBvO9T3rAxy+Kz9wPKu6IFgoMr8ebCEgNbA1OPKqMxqH1ZwDOhN1izaZovUa2GZ /6QeXZm96dqlWb2/P+vdFffMgRqAswl6djHaeUo9uiiwvr0o/mt8YhGWLn2AR6TVZC1J aiEA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698352040; x=1698956840; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=QkDBubNt3gstw368lHcAZnlIM74s0njBq318BQ7+2R0=; b=eA1oc5xLMn4xMH5JdPe6BXp91sWLAAPpKHYuCrdqW2icdwqKT6/clojaK0kn46c7IX wLmMerx02N1S9PBKgWFFexYJLSLR/UCvKos49dxaQQlT8RSVNCFRkgo1M6VTegvOukjN 10lZqfAUVS6R0J3l9r2ZNlvtFX74ssCdegIVdoB8zGdsuZqH3sdOcR3TKaXxBaD4FVy1 XuJf5nvwZdY0lXGYVNO0rmlYAJbIOf90lYqnF/wua1h4+RCi54srm8P7m3voVdScJ6JD QqCh1gaKfxhQZBnHdUV1W/ici4KqR+QRZkwZII0JF0KKoSAlP4EFabFoAO2HuRtELoUN bmJw== X-Gm-Message-State: AOJu0YxiEQfESDvKLB26u8krzajJ07LqXI3H7oD3QS0uBPjvwzt6gz8M NtK+CnUVI/afrRX7Z3x99hai9yRq/XM= X-Google-Smtp-Source: AGHT+IHtWJkzccygjKMSZRalCI9FuUCsvIV8dBsygi3XJHI5pfiRG4z9KvK+kBsyBIXbWokGMVSYcA== X-Received: by 2002:a05:620a:28c2:b0:778:9be8:2742 with SMTP id l2-20020a05620a28c200b007789be82742mr515027qkp.3.1698352039970; Thu, 26 Oct 2023 13:27:19 -0700 (PDT) Received: from LOCLAP699.rst-02.locus (50-78-19-50-static.hfc.comcastbusiness.net. [50.78.19.50]) by smtp.gmail.com with ESMTPSA id r4-20020a05620a298400b007742c2ad7dfsm7303qkp.73.2023.10.26.13.27.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 26 Oct 2023 13:27:19 -0700 (PDT) From: James Prestwood To: iwd@lists.linux.dev Cc: James Prestwood Subject: [PATCH v2 09/15] unit: add DPP test for mutual authentication Date: Thu, 26 Oct 2023 13:26:51 -0700 Message-Id: <20231026202657.183591-10-prestwoj@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231026202657.183591-1-prestwoj@gmail.com> References: <20231026202657.183591-1-prestwoj@gmail.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 --- unit/test-dpp.c | 104 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 99 insertions(+), 5 deletions(-) diff --git a/unit/test-dpp.c b/unit/test-dpp.c index 0cf60f0a..1fa241af 100644 --- a/unit/test-dpp.c +++ b/unit/test-dpp.c @@ -182,6 +182,46 @@ struct dpp_test_vector { const char *ke; const char *mx; const char *nx; + const char *lx; +}; + +/* + * B.1 Test Vectors for DPP Authentication Using P-256 for + * Mutual Authentication + */ +static struct dpp_test_vector mutual_p256 = { + .i_proto_public = "50a532ae2a07207276418d2fa630295d45569be425aa634f02014d00a7d1f61a" + "e14f35a5a858bccad90d126c46594c49ef82655e78888e15a32d916ac2172491", + .i_proto_private = "a87de9afbb406c96e5f79a3df895ecac3ad406f95da66314c8cb3165e0c61783", + /* + * The spec uses a 31 octet Y value, a zero byte was prepended to the + * Y value here otherwise the point cannot be created + */ + .i_boot_public = "88b37ed91938b5197097808a6244847617892046d93b9501afd48fa0f148dfde" + "00f73b6991287884a9c9a33f8e0691f14d44b59811e9d8242d010270b0d33ec0", + .i_boot_private = "15b2a83c5a0a38b61f2aa8200ee4994b8afdc01c58507d10d0a38f7eedf051bb", + .i_nonce = "13f4602a16daeb69712263b9c46cba31", + .i_auth = "d34944bb4b1f05caebda762c6e4ae034c819ec2f62a57dcfade2473876e007b2", + .i_asn1 = "3039301306072a8648ce3d020106082a8648ce3d0301070322000288b37ed919" + "38b5197097808a6244847617892046d93b9501afd48fa0f148dfde", + + .r_proto_public = "5e3fb3576884887f17c3203d8a3a6c2fac722ef0e2201b61ac73bc655c709a90" + "2d4b030669fb9eff8b0a79fa7c1a172ac2a92c626256963f9274dc90682c81e5", + .r_proto_private = "f798ed2e19286f6a6efe210b1863badb99af2a14b497634dbfd2a97394fb5aa5", + .r_boot_public = "09c585a91b4df9fd25a045201885c39cc5cfae397ddaeda957dec57fa0e3503f" + "52bf05968198a2f92883e96a386d767579883302dbf292105c90a43694c2fd5c", + .r_boot_private = "54ce181a98525f217216f59b245f60e9df30ac7f6b26c939418cfc3c42d1afa0", + .r_nonce = "3d0cfb011ca916d796f7029ff0b43393", + .r_auth = "a725abe6dc66ccf3aa3d6d61a19932fcbb0799ed09ff78e5bc6d4ea5ef8e8670", + .r_asn1 = "3039301306072a8648ce3d020106082a8648ce3d0301070322000209c585a91b" + "4df9fd25a045201885c39cc5cfae397ddaeda957dec57fa0e3503f", + + .k1 = "3d832a02ed6d7fc1dc96d2eceab738cf01c0028eb256be33d5a21a720bfcf949", + .k2 = "ca08bdeeef838ddf897a5f01f20bb93dc5a895cb86788ca8c00a7664899bc310", + .ke = "b6db65526c9a0174c3bed56f7e614f3a656233c078693249ac3516425127e5d5", + .mx = "dde2878117d69745be4f916a2dd14269d783d1d788c603bb8746beabbd1dbbbc", + .nx = "92118478b75c21c2c59340c842b5bce560a535f60bc37a75fe390d738c58d8e8", + .lx = "fb737234c973cc3a36e64e5170a32f12089d198c73c2fd85a53d0b282530fd02" }; /* @@ -232,6 +272,8 @@ static void test_key_derivation(const void *data) uint64_t tmp[L_ECC_MAX_DIGITS * 2]; const struct l_ecc_curve *curve = l_ecc_curve_from_ike_group(19); + _auto_(l_ecc_point_free) struct l_ecc_point *i_boot_public = NULL; + _auto_(l_ecc_scalar_free) struct l_ecc_scalar *i_boot_private = NULL; _auto_(l_ecc_point_free) struct l_ecc_point *i_proto_public = NULL; _auto_(l_ecc_point_free) struct l_ecc_point *r_boot_public = NULL; _auto_(l_ecc_scalar_free) struct l_ecc_scalar *r_boot_private = NULL; @@ -239,6 +281,7 @@ static void test_key_derivation(const void *data) _auto_(l_ecc_point_free) struct l_ecc_point *r_proto_public = NULL; _auto_(l_ecc_scalar_free) struct l_ecc_scalar *m = NULL; _auto_(l_ecc_scalar_free) struct l_ecc_scalar *n = NULL; + _auto_(l_ecc_point_free) struct l_ecc_point *l = NULL; _auto_(l_ecc_point_free) struct l_ecc_point *from_asn1 = NULL; uint64_t k1[L_ECC_MAX_DIGITS]; uint64_t k2[L_ECC_MAX_DIGITS]; @@ -262,6 +305,20 @@ static void test_key_derivation(const void *data) tmp, 64); assert(r_boot_public); + if (vector->i_boot_public) { + HEX2BUF(vector->i_boot_public, tmp, 64); + i_boot_public = l_ecc_point_from_data(curve, + L_ECC_POINT_TYPE_FULL, + tmp, 64); + assert(i_boot_public); + } + + if (vector->i_boot_private) { + HEX2BUF(vector->i_boot_private, tmp, 32); + i_boot_private = l_ecc_scalar_new(curve, tmp, 32); + assert(i_boot_private); + } + HEX2BUF(vector->r_asn1, tmp, sizeof(tmp)); asn1 = dpp_point_to_asn1(r_boot_public, &asn1_len); @@ -272,6 +329,19 @@ static void test_key_derivation(const void *data) assert(asn1_len == 59); assert(memcmp(tmp, asn1, asn1_len) == 0); + if (vector->i_asn1) { + HEX2BUF(vector->i_asn1, tmp, sizeof(tmp)); + asn1 = dpp_point_to_asn1(i_boot_public, &asn1_len); + + from_asn1 = dpp_point_from_asn1(asn1, asn1_len); + + assert(l_ecc_points_are_equal(from_asn1, i_boot_public)); + + assert(asn1_len == 59); + assert(memcmp(tmp, asn1, asn1_len) == 0); + } + + HEX2BUF(vector->r_proto_public, tmp, 64); r_proto_public = l_ecc_point_from_data(curve, L_ECC_POINT_TYPE_FULL, @@ -300,18 +370,37 @@ static void test_key_derivation(const void *data) l_ecc_scalar_get_data(n, tmp, sizeof(tmp)); CHECK_FROM_STR(vector->nx, tmp, 32); + if (vector->lx) { + /* Check initiator derivation */ + l = dpp_derive_li(r_boot_public, r_proto_public, + i_boot_private); + assert(l); + l_ecc_point_get_x(l, tmp, sizeof(tmp)); + CHECK_FROM_STR(vector->lx, tmp, 32); + l_ecc_point_free(l); + l = NULL; + + /* Check responder derivation */ + l = dpp_derive_lr(r_boot_private, r_proto_private, + i_boot_public); + assert(l); + l_ecc_point_get_x(l, tmp, sizeof(tmp)); + CHECK_FROM_STR(vector->lx, tmp, 32); + + } + HEX2BUF(vector->i_nonce, i_nonce, 16); HEX2BUF(vector->r_nonce, r_nonce, 16); - dpp_derive_ke(i_nonce, r_nonce, m, n, NULL, ke); + dpp_derive_ke(i_nonce, r_nonce, m, n, l, ke); CHECK_FROM_STR(vector->ke, ke, 32); dpp_derive_r_auth(i_nonce, r_nonce, 16, i_proto_public, r_proto_public, - NULL, r_boot_public, r_auth); + i_boot_public, r_boot_public, r_auth); CHECK_FROM_STR(vector->r_auth, r_auth, 32); dpp_derive_i_auth(r_nonce, i_nonce, 16, r_proto_public, i_proto_public, - r_boot_public, NULL, i_auth); + r_boot_public, i_boot_public, i_auth); CHECK_FROM_STR(vector->i_auth, i_auth, 32); } @@ -320,9 +409,14 @@ int main(int argc, char *argv[]) l_test_init(&argc, &argv); if (l_checksum_is_supported(L_CHECKSUM_SHA256, true) && - l_getrandom_is_supported()) - l_test_add("DPP test key derivation", test_key_derivation, + l_getrandom_is_supported()) { + l_test_add("DPP test responder-only key derivation", + test_key_derivation, &responder_only_p256); + l_test_add("DPP test mutual key derivation", + test_key_derivation, + &mutual_p256); + } l_test_add("DPP URI parse", test_uri_parse, &all_values); l_test_add("DPP URI no type", test_uri_parse, &no_type); From patchwork Thu Oct 26 20:26:52 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Prestwood X-Patchwork-Id: 13437865 Received: from mail-qk1-f170.google.com (mail-qk1-f170.google.com [209.85.222.170]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CAAC53D38E for ; Thu, 26 Oct 2023 20:27:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="jeQTbjoy" Received: by mail-qk1-f170.google.com with SMTP id af79cd13be357-7781bc3783fso101983085a.1 for ; Thu, 26 Oct 2023 13:27:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1698352042; x=1698956842; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=dY229fyI9LCFdAo8JRJ/it3w3S71YIxaVpFzHYbT+tI=; b=jeQTbjoyXAz0DPOAaU7TFteFlZUFBnaUV7DS6QgNx7ceRrjgEriyrteEcohQ5OJbP6 VB42357SzNvGoE2Hj80Yf71Vh9xhlSDFHU7bkwHV2WnBntGAIbJe/lOpAzENHKIsDyJv DlNZk0W/PuJnQh/TLYu5ln1bNUjmMWuhiuyOMsdWUTqeG2AAEAcqV41vlgXBvPufBngj dFYUh2FQOiSJTVmWkkJnO7sue90Uy8s7V4rl7n52rel0lRsNJZZkbIupDt1RTOWY1ZFZ LKpy+BjUbPVWm+aiODrHveWB1fDRALHKt0YGG0M3BSTXq3L8UGr25cJ5z7wWjhj04TqE YISg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698352042; x=1698956842; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=dY229fyI9LCFdAo8JRJ/it3w3S71YIxaVpFzHYbT+tI=; b=tbH9zOS8X2Ai+Yi1aVwPFkxx73rH2vyY/6xte0A7Dbh7rIMb0IUsVjLJa3typqQyw/ bsRDgKXPoMxOJEBpkPNs9vpuv2cVS9+UrqJLkbe+TNIgTXAORyOg1GbCjKMKt6JnrgRg OSgR/+JblKTtEB5mnr4pzgOEgD8Kw2KN3q0IbaAIFbpk9IXgN1MQ0nKwVNMzmQOdeMEQ FjX7IXQM4T5dKMIRDtF5DTHSm8Vdr2B2KwQZFCFhUjxA2mqWdmGNOTfdONR6+3ansW+P OMgMH9Mi0W428rukFMKhuu0wweb8eUI7xD2H2Ja02BYwDC0jsmKoHMPF0h6RkbV3pZ4f ccCw== X-Gm-Message-State: AOJu0YxC84B1aF8vI33rBkUFQgo2eX5zai/zJywEjVe9M2/UJw29Z/0/ 3qcynvfAw8BCohSEc0TD88sN3tkBKG8= X-Google-Smtp-Source: AGHT+IF486NGQLP4yWa7VIf1H9TpPiIFP+jfm7ArIABPJ80mLIdUOP3oUEgRME4iQg3rle9eyjQ2Pw== X-Received: by 2002:a05:620a:4046:b0:774:1470:9a88 with SMTP id i6-20020a05620a404600b0077414709a88mr376463qko.65.1698352042594; Thu, 26 Oct 2023 13:27:22 -0700 (PDT) Received: from LOCLAP699.rst-02.locus (50-78-19-50-static.hfc.comcastbusiness.net. [50.78.19.50]) by smtp.gmail.com with ESMTPSA id r4-20020a05620a298400b007742c2ad7dfsm7303qkp.73.2023.10.26.13.27.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 26 Oct 2023 13:27:22 -0700 (PDT) From: James Prestwood To: iwd@lists.linux.dev Cc: James Prestwood Subject: [PATCH v2 10/15] unit: add PKEX DPP tests Date: Thu, 26 Oct 2023 13:26:52 -0700 Message-Id: <20231026202657.183591-11-prestwoj@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231026202657.183591-1-prestwoj@gmail.com> References: <20231026202657.183591-1-prestwoj@gmail.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 --- unit/test-dpp.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) diff --git a/unit/test-dpp.c b/unit/test-dpp.c index 1fa241af..781d494a 100644 --- a/unit/test-dpp.c +++ b/unit/test-dpp.c @@ -404,6 +404,146 @@ static void test_key_derivation(const void *data) CHECK_FROM_STR(vector->i_auth, i_auth, 32); } +struct dpp_pkex_test_vector { + uint8_t mac_i[6]; + uint8_t mac_r[6]; + const char *identifier; + const char *key; + + const char *i_boot_public; + const char *i_boot_private; + const char *qix; + + const char *r_boot_public; + const char *r_boot_private; + const char *qrx; + + const char *mx; + const char *nx; + + const char *k; + const char *j; + const char *ax; + const char *yx; + const char *xx; + const char *bx; + const char *lx; + + const char *z; + const char *u; + const char *v; +}; + +/* + * Appendix D PKEX Test Vector for NIST p256 + */ +static struct dpp_pkex_test_vector pkex_vector = { + .mac_i = { 0xac, 0x64, 0x91, 0xf4, 0x52, 0x07 }, + .mac_r = { 0x6e, 0x5e, 0xce, 0x6e, 0xf3, 0xdd }, + .identifier = "joes_key", + .key = "thisisreallysecret", + + .i_boot_public = "0ad58864754c812685ff3a52a573c1d72c72c4ebed98f3915622d4dfc84a438d" + "7e81429aac49ddec75ad6521db9c74074e30b5eb2ba53693c9341b79be14e101", + .i_boot_private = "5941b51acfc702cdc1c347264beb2920db88eb1a0bf03a211868b1632233c269", + .qix = "2867c4e080980dbad5099a8f821e8729679c5c714888c0bd9c7e8e4048c5fa5e", + + .r_boot_public = "977b7fa39779a81429febb12e1dc5e20a7e017c4bc7437090e57c966a2b0e8a3" + "9d2b62733947639763f64c7b6708c1e0857becb7e24fc195248b5b06036cf792", + .r_boot_private = "2ae8956293f49986b6d0b8169a86805d9232babb5f6813fdfe96f19d59536c60", + .qrx = "134af1c41c8e7d974c647cc2bfca30b036966959f9044e90f673d756706e624c", + + .mx = "bcca8e23e5c05032ae6051ca6392f7c4a4b4f9fe13e8126132d070e552848176", + .nx = "0a91e0728809bb8191ea36d0a1d5602bf36ab6708fbfd063e2511e533b534020", + + .k = "7415e1c68611f0443cc345d136984e488c6a26d3d5482fa67e9841a03a87c78f", + .j = "31c1b9ab31d9c2f278b35b5c29d180dfeaf76d585ede9c0dd91cb66149db572e", + .ax = "0ad58864754c812685ff3a52a573c1d72c72c4ebed98f3915622d4dfc84a438d", + .yx = "a9972a94f143740df31c7a61124d01a4e949d0fdcede61369f4c6b097aeb18b5", + .xx = "740ab9f0c173507b0081b475b275de6a3060cf434b6a65f0b0144a1dbf913310", + .bx = "977b7fa39779a81429febb12e1dc5e20a7e017c4bc7437090e57c966a2b0e8a3", + .lx = "bc5f3128b0b997079a23ead63cf502ef4f7526602269620377b79bce20e03d44", + + .z = "5271dee915cf7b1908747d8edb8394442411c5183ee38b79ebef399c08738e0b", + .u = "598c3d8dcccea2d43259068d542a907442f07e8cbcfb3fb49faac12eb2fee5b6", + .v = "b2833ce21ab4e42c082111a5dd232334e48019f66b2e274f521fe2f7dfa11999", +}; + +static void test_pkex_key_derivation(const void *user_data) +{ + const struct dpp_pkex_test_vector *vector = user_data; + const struct l_ecc_curve *curve = l_ecc_curve_from_ike_group(19); + uint64_t tmp[L_ECC_MAX_DIGITS * 2]; + _auto_(l_ecc_point_free) struct l_ecc_point *qi = NULL; + _auto_(l_ecc_point_free) struct l_ecc_point *qr = NULL; + _auto_(l_ecc_point_free) struct l_ecc_point *n = NULL; + _auto_(l_ecc_point_free) struct l_ecc_point *m = NULL; + _auto_(l_ecc_point_free) struct l_ecc_point *j = NULL; + _auto_(l_ecc_point_free) struct l_ecc_point *k = NULL; + _auto_(l_ecc_point_free) struct l_ecc_point *a = NULL; + _auto_(l_ecc_point_free) struct l_ecc_point *y = NULL; + _auto_(l_ecc_point_free) struct l_ecc_point *x = NULL; + _auto_(l_ecc_point_free) struct l_ecc_point *b = NULL; + _auto_(l_ecc_point_free) struct l_ecc_point *l = NULL; + size_t len; + + qi = dpp_derive_qi(curve, vector->key, vector->identifier, + vector->mac_i); + l_ecc_point_get_x(qi, tmp, sizeof(tmp)); + CHECK_FROM_STR(vector->qix, tmp, 32); + + qr = dpp_derive_qr(curve, vector->key, vector->identifier, + vector->mac_r); + l_ecc_point_get_x(qr, tmp, sizeof(tmp)); + CHECK_FROM_STR(vector->qrx, tmp, 32); + + HEX2BUF(vector->nx, tmp, 32); + n = l_ecc_point_from_data(curve, L_ECC_POINT_TYPE_COMPLIANT, tmp, 32); + assert(n); + + HEX2BUF(vector->mx, tmp, 32); + m = l_ecc_point_from_data(curve, L_ECC_POINT_TYPE_COMPLIANT, tmp, 32); + assert(m); + + HEX2BUF(vector->k, tmp, 32); + k = l_ecc_point_from_data(curve, L_ECC_POINT_TYPE_COMPLIANT, tmp, 32); + assert(k); + + dpp_derive_z(vector->mac_i, vector->mac_r, n, m, k, vector->key, + vector->identifier, tmp, &len); + CHECK_FROM_STR(vector->z, tmp, 32); + + HEX2BUF(vector->j, tmp, 32); + j = l_ecc_point_from_data(curve, L_ECC_POINT_TYPE_COMPLIANT, tmp, 32); + assert(j); + + HEX2BUF(vector->ax, tmp, 32); + a = l_ecc_point_from_data(curve, L_ECC_POINT_TYPE_COMPLIANT, tmp, 32); + assert(a); + + HEX2BUF(vector->yx, tmp, 32); + y = l_ecc_point_from_data(curve, L_ECC_POINT_TYPE_COMPLIANT, tmp, 32); + assert(y); + + HEX2BUF(vector->xx, tmp, 32); + x = l_ecc_point_from_data(curve, L_ECC_POINT_TYPE_COMPLIANT, tmp, 32); + assert(x); + + dpp_derive_u(j, vector->mac_i, a, y, x, tmp, &len); + CHECK_FROM_STR(vector->u, tmp, 32); + + HEX2BUF(vector->bx, tmp, 32); + b = l_ecc_point_from_data(curve, L_ECC_POINT_TYPE_COMPLIANT, tmp, 32); + assert(b); + + HEX2BUF(vector->lx, tmp, 32); + l = l_ecc_point_from_data(curve, L_ECC_POINT_TYPE_COMPLIANT, tmp, 32); + assert(l); + + dpp_derive_v(l, vector->mac_r, b, x, y, tmp, &len); + CHECK_FROM_STR(vector->v, tmp, 32); +} + int main(int argc, char *argv[]) { l_test_init(&argc, &argv); @@ -416,6 +556,9 @@ int main(int argc, char *argv[]) l_test_add("DPP test mutual key derivation", test_key_derivation, &mutual_p256); + l_test_add("DPP test PKEX key derivation", + test_pkex_key_derivation, + &pkex_vector); } l_test_add("DPP URI parse", test_uri_parse, &all_values); From patchwork Thu Oct 26 20:26:53 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Prestwood X-Patchwork-Id: 13437866 Received: from mail-qk1-f171.google.com (mail-qk1-f171.google.com [209.85.222.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D658B3CD1B for ; Thu, 26 Oct 2023 20:27:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="GpdiWzTF" Received: by mail-qk1-f171.google.com with SMTP id af79cd13be357-7789577b53fso96163285a.3 for ; Thu, 26 Oct 2023 13:27:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1698352044; x=1698956844; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=7EHcA8egXzvk8ZgJPeKkf/wFDqE3BxfTJtKxSVXfzvY=; b=GpdiWzTFQLcdlbyBb9EqU/OdqWgO1tGN0ww1qQgRwcRfZhGNAvJ5mwsTU7Vfaun6i1 K9eKcJ9Rt1GZLRr2CTr+unoKCPEVsZQkmSWI4ePB/SACCWuLtTW0rwlBL2c6jV/dGdkL HHulYAQEP4RoagZHoeRjk0xAVBVgPeT80UKlQmBoKx2sqt2oIL1dQOG1VYqEJANqWkBp Xi5GxGs/DtaMX0nJsQg1Co5cdnGpqyb7Lq6yZ1vOmZSo00mFNYzW8f8x/P0zFk6eqOIn dxGAmubd18BunMXbMFYQmHjO6vWSX3Ba2j2rl1p+iUoj+7P18fx9mRNpU5o5V+52xXCo X7JA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698352044; x=1698956844; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=7EHcA8egXzvk8ZgJPeKkf/wFDqE3BxfTJtKxSVXfzvY=; b=LWDruCYo1HZXDLy4h7qZ13jYxVcBRTrbMTxuyYeMPEkP0I1sjPYubYN1fMrvKv2KcV VPmAOHHoSod22mbxo5m04O4oKfbx8lWeJSGOrk467JIrpA1ARvVGI79Wx3/F/WwEZoS5 45/qKTRvkHfMRBR06dozNpfC9fpfXYnrIbouFTkmXGUYuIc2Qy2kp2hJgAXYXrR9/F1s SFvtW5OuJgyO/ZrCYfdIgzCA7AANdrsbCG8M1mSRp0S8KiMTN9qpX20OjDGSA2EFtlae LY8gcYpd0toQn92JCW62GtSLLVE6plF4Xpd+O/dOiupnrmJz4fT5Wj1LOv3tVK9En4m1 2Ptw== X-Gm-Message-State: AOJu0YwjHTaO53XsRMw/WDgLocGSO5ZX7MSoJyAGYOnucgOKmqwTR733 V1VK/qIAGbwsbOg5XJqciHBxlnUVAzc= X-Google-Smtp-Source: AGHT+IFGzJBu3B+uH7BTocRonlJNlD9stTF7uC8FHrIQKPHIpiiu4aO4HfZj5bPj7sipVD6pWiBeHg== X-Received: by 2002:a05:620a:40c2:b0:775:c5bb:1df9 with SMTP id g2-20020a05620a40c200b00775c5bb1df9mr499964qko.60.1698352044550; Thu, 26 Oct 2023 13:27:24 -0700 (PDT) Received: from LOCLAP699.rst-02.locus (50-78-19-50-static.hfc.comcastbusiness.net. [50.78.19.50]) by smtp.gmail.com with ESMTPSA id r4-20020a05620a298400b007742c2ad7dfsm7303qkp.73.2023.10.26.13.27.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 26 Oct 2023 13:27:24 -0700 (PDT) From: James Prestwood To: iwd@lists.linux.dev Cc: James Prestwood Subject: [PATCH v2 11/15] dpp: allow enrollee to be authentication initiator Date: Thu, 26 Oct 2023 13:26:53 -0700 Message-Id: <20231026202657.183591-12-prestwoj@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231026202657.183591-1-prestwoj@gmail.com> References: <20231026202657.183591-1-prestwoj@gmail.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Until now IWD only supported enrollees as responders (configurators could do both). For PKEX it makes sense for the enrollee to be the initiator because configurators in the area are already on their operating channel and going off is inefficient. For PKEX, whoever initiates also initiates authentication so for this reason the authentication path is being opened up to allow enrollees to initiate. --- src/dpp.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/dpp.c b/src/dpp.c index 77af5669..80167cac 100644 --- a/src/dpp.c +++ b/src/dpp.c @@ -1436,7 +1436,7 @@ static bool dpp_send_authenticate_request(struct dpp_sm *dpp) struct scan_bss *bss = station_get_connected_bss(station); /* Got disconnected by the time the peer was discovered */ - if (!bss) { + if (dpp->role == DPP_CAPABILITY_CONFIGURATOR && !bss) { dpp_reset(dpp); return false; } @@ -1457,7 +1457,8 @@ static bool dpp_send_authenticate_request(struct dpp_sm *dpp) i_proto_key, dpp->key_len * 2); ptr += dpp_append_attr(ptr, DPP_ATTR_PROTOCOL_VERSION, &version, 1); - if (dpp->current_freq != bss->frequency) { + if (dpp->role == DPP_CAPABILITY_CONFIGURATOR && + dpp->current_freq != bss->frequency) { uint8_t pair[2] = { 81, band_freq_to_channel(bss->frequency, NULL) }; @@ -1895,9 +1896,6 @@ static void authenticate_response(struct dpp_sm *dpp, const uint8_t *from, if (dpp->state != DPP_STATE_AUTHENTICATING) return; - if (dpp->role != DPP_CAPABILITY_CONFIGURATOR) - return; - if (!dpp->freqs) return; @@ -2051,6 +2049,10 @@ static void authenticate_response(struct dpp_sm *dpp, const uint8_t *from, dpp->current_freq = dpp->new_freq; dpp_send_authenticate_confirm(dpp); + + if (dpp->role == DPP_CAPABILITY_ENROLLEE) + dpp_configuration_start(dpp, from); + } static void dpp_handle_presence_announcement(struct dpp_sm *dpp, From patchwork Thu Oct 26 20:26:54 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Prestwood X-Patchwork-Id: 13437867 Received: from mail-vk1-f169.google.com (mail-vk1-f169.google.com [209.85.221.169]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 64C4D3D385 for ; Thu, 26 Oct 2023 20:27:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="mxBer+6W" Received: by mail-vk1-f169.google.com with SMTP id 71dfb90a1353d-49d8fbd307fso605261e0c.3 for ; Thu, 26 Oct 2023 13:27:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1698352046; x=1698956846; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=1Snokl7lM4rWTUuRTvaP7DkGU9WjPBKO+MUbZFtNIfM=; b=mxBer+6W/APypAX0i2l+S08rViSY1UjzzLwep776802QtOFOaqrHR8kX3PM2wgHVA1 Ba1k/5QTcr8k3h/kNkWD2JcgypsEZKBqRZKNGAbYFSKTqicnMbEoH63Kg3Ad25aV5leF SAunDfhdARmLMqr5lKTg3NERsMrM9hp9UzOxMCmkQOuZ8XqXgr1EnkUdo2xo9JnDlzCb NpSIxCmBYBlGGccGj329RMnY/GESsr0vGdhA0XqFkB2GMFdC9gU6AMPkQqsRkZDGRK8t 6sMoIkkNnj/OoiIcpFBbeqwZf8Y8i3RYyGEMHrMyYzxNvolmnWgR44Xhm13rHakCLF87 7w5w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698352046; x=1698956846; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=1Snokl7lM4rWTUuRTvaP7DkGU9WjPBKO+MUbZFtNIfM=; b=hx4DSyYtIPW5BznyDzse86p3EqTAOeDt+I4Ve1k4WLXDk9feNsU9OZylDyxgYzCOt/ s3+C0yfLUlgvVAV5c+fcc2fqDjexGl2JlEH3tnNTlllc/RLDb29DQJdbbQGvrsPm9U+L ER/yMMNSYsYOAmTYLzb6YPsgP7E/Qr9aLAmAPsPDNWHoZ7U1oXOzwl9SYAg1h8+AAtPO WEm9MKUn+vgKqd5waJZFWZkSLldwu/v44ng4ud5heNhxiwb6s6PDENh7uMiPodPycSFc GPX+S/S/QW6nOGsBamygxF3H99+MxqWnG1pIH9MbeRAlZtLKXbITaPG7Hl1rZQ+6MUUx +LHQ== X-Gm-Message-State: AOJu0YzbCwJaEu0lNIwx9k7saXyqCDqPc+LdErkqmpHXBpzY20lN0+Nh Zcxar89KmrlH73a35NoNvbFw+zNMIJY= X-Google-Smtp-Source: AGHT+IHrQlyeAafmosM8zuiHeG/3cE4o6mWvLuZ0RP5VYl8QjNXwSSOcWS6r9qzhVj1Ybvwk1KRyqg== X-Received: by 2002:a05:6102:44e:b0:45a:d9e0:88be with SMTP id e14-20020a056102044e00b0045ad9e088bemr783215vsq.21.1698352046081; Thu, 26 Oct 2023 13:27:26 -0700 (PDT) Received: from LOCLAP699.rst-02.locus (50-78-19-50-static.hfc.comcastbusiness.net. [50.78.19.50]) by smtp.gmail.com with ESMTPSA id r4-20020a05620a298400b007742c2ad7dfsm7303qkp.73.2023.10.26.13.27.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 26 Oct 2023 13:27:25 -0700 (PDT) From: James Prestwood To: iwd@lists.linux.dev Cc: James Prestwood Subject: [PATCH v2 12/15] doc: PKEX support for DPP Date: Thu, 26 Oct 2023 13:26:54 -0700 Message-Id: <20231026202657.183591-13-prestwoj@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231026202657.183591-1-prestwoj@gmail.com> References: <20231026202657.183591-1-prestwoj@gmail.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 PKEX is part of the WFA EasyConnect specification and is an additional boostrapping method (like QR codes) for exchanging public keys between a configurator and enrollee. PKEX operates over wifi and requires a key/code be exchanged prior to the protocol. The key is used to encrypt the exchange of the boostrapping information, then DPP authentication is started immediately aftewards. This can be useful for devices which don't have the ability to scan a QR code, or even as a more convenient way to share wireless credentials if the PSK is very secure (i.e. not a human readable string). PKEX would be used via the three DBus APIs on a new interface SharedCodeDeviceProvisioning. ConfigureEnrollee(a{sv}) will start a configurator with a static shared code (optionally identifier) passed in with the dictionary key. StartConfigurator(object agent_path) will start listening and wait for an Enrollee to send a PKEX exchange request. Once received the configurator will call out to an agent (distinguished by 'agent_path') and request the code using the identifier sent by the enrollee. If no identifier was sent the protocol will fail. This method allows for configuring one of several enrollees, assuming the agent has the ability to look up the identifier. StartEnrollee(a{sv}) will start a PKEX enrollee. Enrollees will begin iterating a channel list sending out PKEX exchange requests and waiting for a configurator to respond. After the PKEX protocol is finished, DPP bootstrapping keys have been exchanged and DPP Authentication will start, followed by configuration. --- doc/device-provisioning-api.txt | 67 +++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/doc/device-provisioning-api.txt b/doc/device-provisioning-api.txt index ac204f46..02856571 100644 --- a/doc/device-provisioning-api.txt +++ b/doc/device-provisioning-api.txt @@ -71,3 +71,70 @@ Properties boolean Started [readonly] Indicates the DPP URI. This property is only available when Started is true. + + +Interface net.connman.iwd.SharedCodeDeviceProvisioning [Experimental] +Object path /net/connman/iwd/{phy0,phy1,...}/{1,2,...} + + ConfigureEnrollee(a{sv}) + Starts a DPP configurator using a shared code (and + optionally identifier) set in the dictionary argument. + Valid dictionary keys are: + + { + Code: + Identifier: + } + + As with the DeviceProvisioning interface, configurators + must be currently connected to start. + + Possible errors: net.connman.iwd.Busy + net.connman.iwd.NotConnected + net.connman.InvalidArguments + + StartConfigurator(object agent_path) + Start a shared code configurator using an agent to + obtain the shared code. This method is meant for an + automated use case where a configurator is capable of + configuring multiple enrollees, and distinguishing + between them by their identifier. + + After starting the configurator will listen on channel. + Upon receiving an enrollees initial request it will + make an agent call (on 'agent_path') to obtain the + code associated with the enrollee. + + As with the DeviceProvisioning interface, configurators + must be currently connected to start. + + Possible errors: net.connman.iwd.Busy + net.connman.iwd.NotConnected + net.connman.iwd.InvalidArguments + + StartEnrollee(a{sv}) + Start a shared code enrollee using the Code and + optionally identifier passed in the dictionary argument. + As with the configurator, valid dictionary keys are: + + { + Code: + Identifier: + } + + As with the DeviceProvisioning interface, enrollees + must be disconnected in order to start. + + Possible errors: net.connman.iwd.Busy + net.connman.iwd.InvalidArguments + +Properties boolean Started [readonly] + + True if shared code device provisioning is currently + active. (configurator or enrollee is started) + + string Role [readonly, optional] + + Indicates the DPP role. Possible values are "enrollee" + or "configurator". This property is only available when + Started is true. From patchwork Thu Oct 26 20:26:55 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Prestwood X-Patchwork-Id: 13437868 Received: from mail-qk1-f176.google.com (mail-qk1-f176.google.com [209.85.222.176]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4D04B3D390 for ; Thu, 26 Oct 2023 20:27:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="dli7XKeS" Received: by mail-qk1-f176.google.com with SMTP id af79cd13be357-778927f2dd3so93299385a.2 for ; Thu, 26 Oct 2023 13:27:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1698352048; x=1698956848; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ugoc02Q2FpoXZFBiQ5BqiLP0/t/38mCaTnl1KA/s1cs=; b=dli7XKeSKcGKvXW8ft1wSFkewVSvB0c9wl0f+0o7edBYGiuAP42+uvBpJDkc6Ryd+S ScEAfOq621J+uUilaGoI0pgNj7NurKktRJvHdtGb0mBmGJai9MpT2I9bilVmI4IakoVx g3i9Xpz4dGlpAGYokJcV41Nq3a/5KJRkLxP6jVbbr4xIAqBYPnYwHBEMDp3h+C+5Atk7 Gz8J+sqTISxy/0oU2OkDXxa/isH/ed7A60IY58e10I8197bLUdeASE9Cw0odYQfthm5j OQdZsZDMLGV7LDH40YA2kNgFENw/DmHOEncmguYtJ1rPg/l/ZYOXe69T7VT+Z0mCO/Uf EDLg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698352048; x=1698956848; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ugoc02Q2FpoXZFBiQ5BqiLP0/t/38mCaTnl1KA/s1cs=; b=SZOdUrOjXO2eGWig9orE+ENfbbWXMSePnGBtUxvTey0Kpp6ts2slMBwAvbG3t+zh4f 6cXpIDCCRuBaUlbsn/hJDrzN7Up53l6XUFZY7PfeATiYLHA7F0KNbyEYBzeDpq5MPMGk 5IOTxwP+b2doph4bjRQr1bCvMYZsATAf7/qNzUWd2zvueNzjz5tz6qBMrvZ+C0L8KHr5 YPFhbQgZR7kgleGPby4NVutccNTLsgWYrRCWexh6t7vecghwJq1HfLm6k2PBjarlfVJ6 nqsV2qnY8nXYnacR5PVRwroLCUODo8dPn680/IUbSsn1cZ51/kBBSw8nzzT1VhLkhIoZ g/+Q== X-Gm-Message-State: AOJu0YwrNsOr0BNJN3KnDjhvaeC16kLk/Z2UnpaoOl17+UE1vztsZegi aRByXfhPpOicGatjrxeRIGfv4unjVZg= X-Google-Smtp-Source: AGHT+IF5dT8kN7vk7AByOcAL1Ytw93ZfPdx64bPHRFHHGtPwrwYriGMi9BJL8z1A5mSl/0QxIUrbtQ== X-Received: by 2002:a05:620a:1794:b0:775:9f9d:2c36 with SMTP id ay20-20020a05620a179400b007759f9d2c36mr404306qkb.54.1698352048024; Thu, 26 Oct 2023 13:27:28 -0700 (PDT) Received: from LOCLAP699.rst-02.locus (50-78-19-50-static.hfc.comcastbusiness.net. [50.78.19.50]) by smtp.gmail.com with ESMTPSA id r4-20020a05620a298400b007742c2ad7dfsm7303qkp.73.2023.10.26.13.27.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 26 Oct 2023 13:27:27 -0700 (PDT) From: James Prestwood To: iwd@lists.linux.dev Cc: James Prestwood Subject: [PATCH v2 13/15] dbus: add SharedCodeDeviceProvisioning interface definition Date: Thu, 26 Oct 2023 13:26:55 -0700 Message-Id: <20231026202657.183591-14-prestwoj@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231026202657.183591-1-prestwoj@gmail.com> References: <20231026202657.183591-1-prestwoj@gmail.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 --- src/dbus.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dbus.h b/src/dbus.h index 00c2df57..cff64ae2 100644 --- a/src/dbus.h +++ b/src/dbus.h @@ -44,6 +44,7 @@ #define IWD_AP_DIAGNOSTIC_INTERFACE "net.connman.iwd.AccessPointDiagnostic" #define IWD_STATION_DEBUG_INTERFACE "net.connman.iwd.StationDebug" #define IWD_DPP_INTERFACE "net.connman.iwd.DeviceProvisioning" +#define IWD_DPP_PKEX_INTERFACE "net.connman.iwd.SharedCodeDeviceProvisioning" #define IWD_NETCONFIG_AGENT_INTERFACE \ "net.connman.iwd.NetworkConfigurationAgent" From patchwork Thu Oct 26 20:26:56 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: James Prestwood X-Patchwork-Id: 13437869 Received: from mail-qk1-f175.google.com (mail-qk1-f175.google.com [209.85.222.175]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 42A4D3D38E for ; Thu, 26 Oct 2023 20:27:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="lYOOTwak" Received: by mail-qk1-f175.google.com with SMTP id af79cd13be357-7781bc3783fso101993185a.1 for ; Thu, 26 Oct 2023 13:27:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1698352050; x=1698956850; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=7n19EHoXqxI+fCZpewolye7gTaT4SVouCvkjFi0EcXw=; b=lYOOTwaklXC+uwLoz6c36X2cYNC+c9jsVwaVZUpEf23vJBBOCSHFeRyYR3bjhQNvmQ QdVhUfrxZ8iI2NnpgPbkGCwjB8773sbrVlyVHF9joPpFOYOcxrv/oxGCW3lferDhNNoy 9kPL9iejaTIgnxZg1o+WptTtE3CmSwoLwfzKwOtGikZJgEHkV3ZZ9Upuq97WCMb6Ti4Q fQRYjSBUXeiJfRlm0iMrYU3+OnqlObqt9/tfdun3vpiOk6UibjhBezdzB6Q3QGVvNdbi WM+WQeoo31SLDGX7xyjw3GIHR94vSc8mhWPVkxn/7Wp6qUxbTdRgxNusSuqfNM3FUMmy 2e8Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698352050; x=1698956850; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=7n19EHoXqxI+fCZpewolye7gTaT4SVouCvkjFi0EcXw=; b=t0umNe5bU07yJNttV9S4+0HGKvIvqDDZWPn9f3gLuIfBXJxQ+Csd+8qAtWlvEFa/1/ N+Q88hfo6wo4u0ZUeR+fAj4CqQWEmA0yO+/h9PhKvBylG7KEMA/BoIyfUqlOhMVdSjn+ HXiQTmA/8CLyecnS4dyN8q4uRM9PzcFzV63H5ScZ45iM8t1RHsYieoUnBYHmPF6N4AxT F/NFhgzPBovVfyPmxxN2nVVHIQkLwL+mCf9K8gpW8ptR+SP5gw2K5gAx8aJrsFt9SdIf JxZNa+MRCJosMzkfBGvurOqknUkw50nCKqRxtSPm9Pau98WJ+IUX7Bnrsy3N2aW8jmWV 5oJA== X-Gm-Message-State: AOJu0YweqtHWTSG+m4lMtq3+/PeEa4IJFwyS21jl+1lu4WIE9BcvJ9G3 MOFOMyyEpoqj4toJATvI46hZhuJQjAk= X-Google-Smtp-Source: AGHT+IH5toBCaSheUqWSvSfaf7yAxqvr15VGmkxJ0T2XNitYa9l4dQzBdnyw0Msddm3WvgkwJFKf2g== X-Received: by 2002:a05:620a:400a:b0:778:a62a:2c4b with SMTP id h10-20020a05620a400a00b00778a62a2c4bmr442317qko.47.1698352049454; Thu, 26 Oct 2023 13:27:29 -0700 (PDT) Received: from LOCLAP699.rst-02.locus (50-78-19-50-static.hfc.comcastbusiness.net. [50.78.19.50]) by smtp.gmail.com with ESMTPSA id r4-20020a05620a298400b007742c2ad7dfsm7303qkp.73.2023.10.26.13.27.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 26 Oct 2023 13:27:29 -0700 (PDT) From: James Prestwood To: iwd@lists.linux.dev Cc: James Prestwood Subject: [PATCH v2 14/15] dpp: initial version of PKEX enrollee support Date: Thu, 26 Oct 2023 13:26:56 -0700 Message-Id: <20231026202657.183591-15-prestwoj@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231026202657.183591-1-prestwoj@gmail.com> References: <20231026202657.183591-1-prestwoj@gmail.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This is the initial support for PKEX enrollees acting as the initiator. A PKEX initiator starts the protocol by broadcasting the PKEX exchange request. This request contains a key encrypted with the pre-shared PKEX code. If accepted the peer sends back the exchange response with its own encrypted key. The enrollee decrypts this and performs some crypto/hashing in order to establish an ephemeral key used to encrypt its own boostrapping key. The boostrapping key is encrypted and sent to the peer in the PKEX commit-reveal request. The peer then does the same thing, encrypting its own bootstrapping key and sending to the initiator as the PKEX commit-reveal response. After this, both peers have exchanged their boostrapping keys securely and can begin DPP authentication, then configuration. For now the enrollee will only iterate the default channel list from the Easy Connect spec. Future upates will need to include some way of discovering non-default channel configurators, but the protocol needs to be ironed out first. --- src/dpp.c | 785 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 781 insertions(+), 4 deletions(-) diff --git a/src/dpp.c b/src/dpp.c index 80167cac..9d99cd50 100644 --- a/src/dpp.c +++ b/src/dpp.c @@ -53,10 +53,12 @@ #include "src/network.h" #include "src/handshake.h" #include "src/nl80211util.h" +#include "src/agent.h" #define DPP_FRAME_MAX_RETRIES 5 #define DPP_FRAME_RETRY_TIMEOUT 1 #define DPP_AUTH_PROTO_TIMEOUT 10 +#define DPP_PKEX_PROTO_TIMEOUT 120 static uint32_t netdev_watch; static struct l_genl_family *nl80211; @@ -70,6 +72,8 @@ static uint8_t dpp_prefix[] = { 0x04, 0x09, 0x50, 0x6f, 0x9a, 0x1a, 0x01 }; enum dpp_state { DPP_STATE_NOTHING, DPP_STATE_PRESENCE, + DPP_STATE_PKEX_EXCHANGE, + DPP_STATE_PKEX_COMMIT_REVEAL, DPP_STATE_AUTHENTICATING, DPP_STATE_CONFIGURING, DPP_STATE_SUCCESS, @@ -147,6 +151,21 @@ struct dpp_sm { struct l_dbus_message *pending; + /* PKEX-specific values */ + char *pkex_id; + char *pkex_key; + uint8_t pkex_version; + struct l_ecc_point *pkex_m; + /* Ephemeral key Y' or X' for enrollee or configurator */ + struct l_ecc_point *y_or_x; + /* Ephemeral key pair y/Y or x/X */ + struct l_ecc_point *pkex_public; + struct l_ecc_scalar *pkex_private; + uint8_t z[L_ECC_SCALAR_MAX_BYTES]; + size_t z_len; + uint8_t u[L_ECC_SCALAR_MAX_BYTES]; + size_t u_len; + bool mcast_support : 1; bool roc_started : 1; bool channel_switch : 1; @@ -154,13 +173,45 @@ struct dpp_sm { bool mutual_auth : 1; }; +static bool dpp_pkex_get_started(struct l_dbus *dbus, + struct l_dbus_message *message, + struct l_dbus_message_builder *builder, + void *user_data) +{ + struct dpp_sm *dpp = user_data; + bool started = false; + + switch (dpp->state) { + case DPP_STATE_PKEX_EXCHANGE: + case DPP_STATE_PKEX_COMMIT_REVEAL: + started = true; + break; + default: + break; + } + + l_dbus_message_builder_append_basic(builder, 'b', &started); + + return true; +} + static bool dpp_get_started(struct l_dbus *dbus, struct l_dbus_message *message, struct l_dbus_message_builder *builder, void *user_data) { struct dpp_sm *dpp = user_data; - bool started = (dpp->state != DPP_STATE_NOTHING); + bool started = false; + + switch (dpp->state) { + case DPP_STATE_PRESENCE: + case DPP_STATE_AUTHENTICATING: + case DPP_STATE_CONFIGURING: + started = true; + break; + default: + break; + } l_dbus_message_builder_append_basic(builder, 'b', &started); @@ -200,7 +251,9 @@ static bool dpp_get_uri(struct l_dbus *dbus, { struct dpp_sm *dpp = user_data; - if (dpp->state == DPP_STATE_NOTHING) + if (dpp->state == DPP_STATE_NOTHING || + dpp->state == DPP_STATE_PKEX_EXCHANGE || + dpp->state == DPP_STATE_PKEX_COMMIT_REVEAL) return false; l_dbus_message_builder_append_basic(builder, 's', dpp->uri); @@ -219,6 +272,16 @@ static void dpp_property_changed_notify(struct dpp_sm *dpp) "URI"); } +static void dpp_pkex_property_changed_notify(struct dpp_sm *dpp) +{ + const char *path = netdev_get_path(dpp->netdev); + + l_dbus_property_changed(dbus_get_bus(), path, IWD_DPP_PKEX_INTERFACE, + "Started"); + l_dbus_property_changed(dbus_get_bus(), path, IWD_DPP_PKEX_INTERFACE, + "Role"); +} + static void *dpp_serialize_iovec(struct iovec *iov, size_t iov_len, size_t *out_len) { @@ -269,6 +332,27 @@ static void dpp_free_auth_data(struct dpp_sm *dpp) l_ecc_scalar_free(dpp->m); dpp->m = NULL; } + + if (dpp->pkex_m) { + l_ecc_point_free(dpp->pkex_m); + dpp->pkex_m = NULL; + } + + if (dpp->y_or_x) { + l_ecc_point_free(dpp->y_or_x); + dpp->y_or_x = NULL; + } + + if (dpp->pkex_public) { + l_ecc_point_free(dpp->pkex_public); + dpp->pkex_public = NULL; + } + + if (dpp->pkex_private) { + l_ecc_scalar_free(dpp->pkex_private); + dpp->pkex_private = NULL; + } + } static void dpp_reset(struct dpp_sm *dpp) @@ -337,10 +421,24 @@ static void dpp_reset(struct dpp_sm *dpp) explicit_bzero(dpp->k1, dpp->key_len); explicit_bzero(dpp->k2, dpp->key_len); explicit_bzero(dpp->auth_tag, dpp->key_len); + explicit_bzero(dpp->z, dpp->key_len); + explicit_bzero(dpp->u, dpp->u_len); + + if (dpp->pkex_key) { + explicit_bzero(dpp->pkex_key, strlen(dpp->pkex_key)); + l_free(dpp->pkex_key); + dpp->pkex_key = NULL; + } + + if (dpp->pkex_id) { + l_free(dpp->pkex_id); + dpp->pkex_id = NULL; + } dpp_free_auth_data(dpp); dpp_property_changed_notify(dpp); + dpp_pkex_property_changed_notify(dpp); } static void dpp_free(struct dpp_sm *dpp) @@ -365,6 +463,23 @@ static void dpp_free(struct dpp_sm *dpp) l_free(dpp); } +static bool dpp_check_pkex_identifier(const char *id) +{ + const char *end; + + if (!id) + return true; + + /* + * "If an optional code identifier is used, it shall be a UTF-8 string + * not greater than eighty (80) octets" + */ + if (!l_utf8_validate(id, strlen(id), &end) || end - id > 80) + return false; + + return true; +} + static void dpp_send_frame_cb(struct l_genl_msg *msg, void *user_data) { struct dpp_sm *dpp = user_data; @@ -1479,6 +1594,71 @@ static bool dpp_send_authenticate_request(struct dpp_sm *dpp) return true; } +static void dpp_send_pkex_exchange_request(struct dpp_sm *dpp) +{ + uint8_t hdr[32]; + uint8_t attrs[256]; + uint8_t *ptr = attrs; + uint64_t m_data[L_ECC_MAX_DIGITS * 2]; + uint16_t group; + struct iovec iov[2]; + const uint8_t *own_mac = netdev_get_address(dpp->netdev); + + l_put_le16(l_ecc_curve_get_ike_group(dpp->curve), &group); + + iov[0].iov_len = dpp_build_header(own_mac, broadcast, + DPP_FRAME_PKEX_VERSION1_XCHG_REQUST, hdr); + iov[0].iov_base = hdr; + + ptr += dpp_append_attr(ptr, DPP_ATTR_PROTOCOL_VERSION, + &dpp->pkex_version, 1); + ptr += dpp_append_attr(ptr, DPP_ATTR_FINITE_CYCLIC_GROUP, + &group, 2); + + if (dpp->pkex_id) + ptr += dpp_append_attr(ptr, DPP_ATTR_CODE_IDENTIFIER, + dpp->pkex_id, strlen(dpp->pkex_id)); + + l_ecc_point_get_data(dpp->pkex_m, m_data, sizeof(m_data)); + + ptr += dpp_append_attr(ptr, DPP_ATTR_ENCRYPTED_KEY, + m_data, dpp->key_len * 2); + + iov[1].iov_base = attrs; + iov[1].iov_len = ptr - attrs; + + dpp_send_frame(dpp, iov, 2, dpp->current_freq); +} + +static void dpp_send_commit_reveal_request(struct dpp_sm *dpp) +{ + struct iovec iov[2]; + uint8_t hdr[41]; + uint8_t attrs[512]; + uint8_t *ptr = attrs; + uint8_t zero = 0; + uint8_t a_pub[L_ECC_POINT_MAX_BYTES]; + ssize_t a_len; + + a_len = l_ecc_point_get_data(dpp->boot_public, a_pub, sizeof(a_pub)); + + iov[0].iov_len = dpp_build_header(netdev_get_address(dpp->netdev), + dpp->peer_addr, + DPP_FRAME_PKEX_COMMIT_REVEAL_REQUEST, + hdr); + iov[0].iov_base = hdr; + + ptr += dpp_append_wrapped_data(hdr + 26, 6, &zero, 1, ptr, + sizeof(attrs), dpp->z, dpp->z_len, 2, + DPP_ATTR_BOOTSTRAPPING_KEY, a_len, a_pub, + DPP_ATTR_INITIATOR_AUTH_TAG, dpp->u_len, dpp->u); + + iov[1].iov_base = attrs; + iov[1].iov_len = ptr - attrs; + + dpp_send_frame(dpp, iov, 2, dpp->current_freq); +} + static void dpp_roc_started(void *user_data) { struct dpp_sm *dpp = user_data; @@ -1542,6 +1722,16 @@ static void dpp_roc_started(void *user_data) send_authenticate_response(dpp); } + break; + case DPP_STATE_PKEX_EXCHANGE: + if (dpp->role == DPP_CAPABILITY_ENROLLEE) + dpp_send_pkex_exchange_request(dpp); + + break; + case DPP_STATE_PKEX_COMMIT_REVEAL: + if (dpp->role == DPP_CAPABILITY_ENROLLEE) + dpp_send_commit_reveal_request(dpp); + break; default: break; @@ -1571,6 +1761,7 @@ static void dpp_offchannel_timeout(int error, void *user_data) switch (dpp->state) { case DPP_STATE_PRESENCE: + case DPP_STATE_PKEX_EXCHANGE: break; case DPP_STATE_NOTHING: case DPP_STATE_SUCCESS: @@ -1578,6 +1769,7 @@ static void dpp_offchannel_timeout(int error, void *user_data) return; case DPP_STATE_AUTHENTICATING: case DPP_STATE_CONFIGURING: + case DPP_STATE_PKEX_COMMIT_REVEAL: goto next_roc; } @@ -2140,6 +2332,383 @@ static void dpp_handle_presence_announcement(struct dpp_sm *dpp, dpp->channel_switch = true; } +static void dpp_pkex_bad_group(struct dpp_sm *dpp, uint16_t group) +{ + uint16_t own_group = l_ecc_curve_get_ike_group(dpp->curve); + + /* + * TODO: The spec allows group negotiation, but it is not yet + * implemented. + */ + if (!group) + return; + /* + * Section 5.6.2 + * "If the Responder's offered group offers less security + * than the Initiator's offered group, then the Initiator should + * ignore this message" + */ + if (group < own_group) { + l_debug("Offered group %u is less secure, ignoring", + group); + return; + } + /* + * Section 5.6.2 + * "If the Responder's offered group offers equivalent or better + * security than the Initiator's offered group, then the + * Initiator may choose to abort its original request and try + * another exchange using the group offered by the Responder" + */ + if (group >= own_group) { + l_debug("Offered group %u is the same or more secure, " + " but group negotiation is not supported", group); + return; + } +} + +static void dpp_pkex_bad_code(struct dpp_sm *dpp) +{ + _auto_(l_ecc_point_free) struct l_ecc_point *qr = NULL; + + qr = dpp_derive_qr(dpp->curve, dpp->pkex_key, dpp->pkex_id, + netdev_get_address(dpp->netdev)); + if (!qr || l_ecc_point_is_infinity(qr)) { + l_debug("Qr computed to zero, new code should be provisioned"); + return; + } + + l_debug("Qr computed successfully but responder indicated otherwise"); +} + +static void dpp_handle_pkex_exchange_response(struct dpp_sm *dpp, + const uint8_t *from, + const uint8_t *body, size_t body_len) +{ + struct dpp_attr_iter iter; + enum dpp_attribute_type type; + size_t len; + const uint8_t *data; + const uint8_t *status = NULL; + uint8_t version = 0; + const char *identifier = NULL; + size_t identifier_len = 0; + const void *key = NULL; + size_t key_len = 0; + uint16_t group = 0; + _auto_(l_ecc_point_free) struct l_ecc_point *n = NULL; + _auto_(l_ecc_point_free) struct l_ecc_point *j = NULL; + _auto_(l_ecc_point_free) struct l_ecc_point *qr = NULL; + _auto_(l_ecc_point_free) struct l_ecc_point *k = NULL; + const uint8_t *own_addr = netdev_get_address(dpp->netdev); + + l_debug("PKEX response "MAC, MAC_STR(from)); + + if (dpp->state != DPP_STATE_PKEX_EXCHANGE) + return; + + if (dpp->role != DPP_CAPABILITY_ENROLLEE) + return; + + memcpy(dpp->peer_addr, from, 6); + + dpp_attr_iter_init(&iter, body + 8, body_len - 8); + + while (dpp_attr_iter_next(&iter, &type, &len, &data)) { + switch (type) { + case DPP_ATTR_STATUS: + if (len != 1) + return; + + status = data; + break; + case DPP_ATTR_PROTOCOL_VERSION: + if (len != 1) + return; + + version = l_get_u8(data); + break; + case DPP_ATTR_CODE_IDENTIFIER: + identifier = (char *) data; + identifier_len = len; + break; + case DPP_ATTR_ENCRYPTED_KEY: + if (len != dpp->key_len * 2) + return; + + key = data; + key_len = len; + break; + case DPP_ATTR_FINITE_CYCLIC_GROUP: + if (len != 2) + return; + + group = l_get_le16(data); + break; + default: + break; + } + } + + if (!status) { + l_debug("No status attribute, ignoring"); + return; + } + + if (!key) { + l_debug("No encrypted key, ignoring"); + return; + } + + if (*status != DPP_STATUS_OK) + goto handle_status; + + if (dpp->pkex_id) { + if (!identifier || identifier_len != strlen(dpp->pkex_id) || + strncmp(dpp->pkex_id, identifier, + identifier_len)) { + l_debug("mismatch identifier, ignoring"); + return; + } + } + + if (version && version != dpp->pkex_version) { + l_debug("PKEX version does not match, igoring"); + return; + } + + n = l_ecc_point_from_data(dpp->curve, L_ECC_POINT_TYPE_FULL, + key, key_len); + if (!n) { + l_debug("failed to parse peers encrypted key"); + goto failed; + } + + qr = dpp_derive_qr(dpp->curve, dpp->pkex_key, dpp->pkex_id, + dpp->peer_addr); + if (!qr) + goto failed; + + dpp->y_or_x = l_ecc_point_new(dpp->curve); + + /* Y' = N - Qr */ + l_ecc_point_inverse(qr); + l_ecc_point_add(dpp->y_or_x, n, qr); + + /* + * "The resulting ephemeral key, denoted Y’, is then checked whether it + * is the point-at-infinity. If it is not valid, the protocol ends + * unsuccessfully" + */ + if (l_ecc_point_is_infinity(dpp->y_or_x)) { + l_debug("Y' computed to infinity, failing"); + goto failed; + } + + k = l_ecc_point_new(dpp->curve); + + /* K = Y' * x */ + l_ecc_point_multiply(k, dpp->pkex_private, dpp->y_or_x); + + dpp_derive_z(own_addr, dpp->peer_addr, n, dpp->pkex_m, k, + dpp->pkex_key, dpp->pkex_id, + dpp->z, &dpp->z_len); + + /* J = a * Y' */ + j = l_ecc_point_new(dpp->curve); + + l_ecc_point_multiply(j, dpp->boot_private, dpp->y_or_x); + + if (!dpp_derive_u(j, own_addr, dpp->boot_public, dpp->y_or_x, + dpp->pkex_public, dpp->u, &dpp->u_len)) { + l_debug("failed to compute u"); + goto failed; + } + + /* + * Now that a response was successfully received, start another + * offchannel with more time for the remainder of the protocol. After + * PKEX, authentication will begin which handles the protocol timeout. + * If the remainder of PKEX (commit-reveal exchange) cannot complete in + * this time it will fail. + */ + dpp->dwell = (dpp->max_roc < 2000) ? dpp->max_roc : 2000; + dpp->state = DPP_STATE_PKEX_COMMIT_REVEAL; + + dpp_pkex_property_changed_notify(dpp); + + dpp_start_offchannel(dpp, dpp->current_freq); + + return; + +handle_status: + switch (*status) { + case DPP_STATUS_BAD_GROUP: + dpp_pkex_bad_group(dpp, group); + break; + case DPP_STATUS_BAD_CODE: + dpp_pkex_bad_code(dpp); + break; + default: + l_debug("Unhandled status %u", *status); + break; + } + +failed: + dpp_reset(dpp); +} + +static bool dpp_pkex_start_authentication(struct dpp_sm *dpp) +{ + dpp->uri = dpp_generate_uri(dpp->own_asn1, dpp->own_asn1_len, 2, + netdev_get_address(dpp->netdev), + &dpp->current_freq, 1, NULL, NULL); + + l_ecdh_generate_key_pair(dpp->curve, &dpp->proto_private, + &dpp->own_proto_public); + + l_getrandom(dpp->i_nonce, dpp->nonce_len); + + dpp->peer_asn1 = dpp_point_to_asn1(dpp->peer_boot_public, + &dpp->peer_asn1_len); + + dpp->m = dpp_derive_k1(dpp->peer_boot_public, dpp->proto_private, + dpp->k1); + + dpp_hash(L_CHECKSUM_SHA256, dpp->peer_boot_hash, 1, dpp->peer_asn1, + dpp->peer_asn1_len); + + dpp->state = DPP_STATE_AUTHENTICATING; + dpp->mutual_auth = true; + + dpp_pkex_property_changed_notify(dpp); + + if (dpp->role == DPP_CAPABILITY_ENROLLEE) { + dpp->new_freq = dpp->current_freq; + + return dpp_send_authenticate_request(dpp); + } + + return true; +} + + +static void dpp_handle_pkex_commit_reveal_response(struct dpp_sm *dpp, + const uint8_t *from, + const uint8_t *body, size_t body_len) +{ + struct dpp_attr_iter iter; + enum dpp_attribute_type type; + size_t len; + const uint8_t *data; + const uint8_t *wrapped = NULL; + size_t wrapped_len = 0; + uint8_t one = 1; + _auto_(l_free) uint8_t *unwrapped = NULL; + size_t unwrapped_len = 0; + const uint8_t *boot_key = NULL; + size_t boot_key_len = 0; + const uint8_t *r_auth = NULL; + uint8_t v[L_ECC_SCALAR_MAX_BYTES]; + size_t v_len; + _auto_(l_ecc_point_free) struct l_ecc_point *l = NULL; + + l_debug("PKEX commit reveal "MAC, MAC_STR(from)); + + if (dpp->state != DPP_STATE_PKEX_COMMIT_REVEAL) + return; + + if (dpp->role != DPP_CAPABILITY_ENROLLEE) + return; + + /* + * The URI may not have contained a MAC address, if this announcement + * verifies set peer_addr then. + */ + if (memcmp(from, dpp->peer_addr, 6)) { + l_debug("Unexpected source "MAC" expected "MAC, MAC_STR(from), + MAC_STR(dpp->peer_addr)); + return; + } + + dpp_attr_iter_init(&iter, body + 8, body_len - 8); + + while (dpp_attr_iter_next(&iter, &type, &len, &data)) { + switch (type) { + case DPP_ATTR_WRAPPED_DATA: + wrapped = data; + wrapped_len = len; + break; + default: + break; + } + } + + if (!wrapped) { + l_debug("No wrapped data"); + return; + } + + unwrapped = dpp_unwrap_attr(body + 2, 6, &one, 1, dpp->z, dpp->z_len, + wrapped, wrapped_len, &unwrapped_len); + if (!unwrapped) { + l_debug("Failed to unwrap Reveal-Commit message"); + return; + } + + dpp_attr_iter_init(&iter, unwrapped, unwrapped_len); + + while (dpp_attr_iter_next(&iter, &type, &len, &data)) { + switch (type) { + case DPP_ATTR_BOOTSTRAPPING_KEY: + if (len != dpp->key_len * 2) + return; + + boot_key = data; + boot_key_len = len; + break; + case DPP_ATTR_RESPONDER_AUTH_TAG: + if (len != 32) + return; + + r_auth = data; + break; + default: + break; + } + } + + dpp->peer_boot_public = l_ecc_point_from_data(dpp->curve, + L_ECC_POINT_TYPE_FULL, + boot_key, boot_key_len); + if (!dpp->peer_boot_public) { + l_debug("Peer public bootstrapping key was invalid"); + goto failed; + } + + /* L = b * X' */ + l = l_ecc_point_new(dpp->curve); + + l_ecc_point_multiply(l, dpp->pkex_private, dpp->peer_boot_public); + + if (!dpp_derive_v(l, dpp->peer_addr, dpp->peer_boot_public, + dpp->pkex_public, dpp->y_or_x, v, &v_len)) { + l_debug("Failed to derive v"); + goto failed; + } + + if (memcmp(v, r_auth, v_len)) { + l_debug("Bootstrapping data did not verify"); + goto failed; + } + + if (dpp_pkex_start_authentication(dpp)) + return; + +failed: + dpp_reset(dpp); +} + static void dpp_handle_frame(struct dpp_sm *dpp, const struct mmpdu_header *frame, const void *body, size_t body_len) @@ -2174,6 +2743,14 @@ static void dpp_handle_frame(struct dpp_sm *dpp, dpp_handle_presence_announcement(dpp, frame->address_2, body, body_len); break; + case DPP_FRAME_PKEX_XCHG_RESPONSE: + dpp_handle_pkex_exchange_response(dpp, frame->address_2, body, + body_len); + break; + case DPP_FRAME_PKEX_COMMIT_REVEAL_RESPONSE: + dpp_handle_pkex_commit_reveal_response(dpp, frame->address_2, + body, body_len); + break; default: l_debug("Unhandled DPP frame %u", *ptr); break; @@ -2230,10 +2807,16 @@ static void dpp_mlme_notify(struct l_genl_msg *msg, void *user_data) if (!dpp) return; - if (dpp->state <= DPP_STATE_PRESENCE) + /* + * Don't retransmit for presence or PKEX exchange if an enrollee, both + * are broadcast frames which don't expect an ack. + */ + if (dpp->state == DPP_STATE_NOTHING || + dpp->state == DPP_STATE_PRESENCE || + (dpp->state == DPP_STATE_PKEX_EXCHANGE && + dpp->role == DPP_CAPABILITY_ENROLLEE)) return; - if (dpp->frame_cookie != cookie) return; @@ -2403,6 +2986,8 @@ static void dpp_create(struct netdev *netdev) l_dbus_object_add_interface(dbus, netdev_get_path(netdev), IWD_DPP_INTERFACE, dpp); + l_dbus_object_add_interface(dbus, netdev_get_path(netdev), + IWD_DPP_PKEX_INTERFACE, dpp); dpp_frame_watch(dpp, 0x00d0, dpp_prefix, sizeof(dpp_prefix)); @@ -2716,6 +3301,182 @@ static struct l_dbus_message *dpp_dbus_stop(struct l_dbus *dbus, return l_dbus_message_new_method_return(message); } +/* + * Section 5.6.1 + * In lieu of specific channel information obtained in a manner outside + * the scope of this specification, PKEX responders shall select one of + * the following channels: + * - 2.4 GHz: Channel 6 (2.437 GHz) + * - 5 GHz: Channel 44 (5.220 GHz) if local regulations permit + * operation only in the 5.150 – 5.250 GHz band and Channel + * 149 (5.745 GHz) otherwise + */ +static uint32_t *dpp_default_freqs(struct dpp_sm *dpp, size_t *out_len) +{ + struct wiphy *wiphy = wiphy_find_by_wdev(dpp->wdev_id); + const uint32_t default_channels[] = { 2437, 5220, 5745 }; + uint32_t *freqs_out; + size_t i; + size_t len = 1; + + if (wiphy_get_supported_bands(wiphy) & BAND_FREQ_5_GHZ) + len += 2; + + freqs_out = l_new(uint32_t, len); + + for (i = 0; i < 3; i++) + freqs_out[i] = default_channels[i]; + + *out_len = len; + return freqs_out; +} + +static bool dpp_start_pkex_enrollee(struct dpp_sm *dpp, const char *key, + const char *identifier) +{ + struct station *station = station_find(netdev_get_ifindex(dpp->netdev)); + _auto_(l_ecc_point_free) struct l_ecc_point *qi = NULL; + + if (station && station_get_connected_network(station)) { + l_debug("Already connected, disconnect before enrolling"); + return false; + } + + if (identifier) + dpp->pkex_id = l_strdup(identifier); + + dpp->pkex_key = l_strdup(key); + memcpy(dpp->peer_addr, broadcast, 6); + dpp->role = DPP_CAPABILITY_ENROLLEE; + dpp->state = DPP_STATE_PKEX_EXCHANGE; + /* + * In theory a driver could support a lesser duration than 200ms. This + * complicates things since we would need to tack on additional + * offchannel requests to meet the 200ms requirement. This could be done + * but for now use max_roc or 200ms, whichever is less. + */ + dpp->dwell = (dpp->max_roc < 200) ? dpp->max_roc : 200; + /* "DPP R2 devices are expected to use PKEXv1 by default" */ + dpp->pkex_version = 1; + + if (!l_ecdh_generate_key_pair(dpp->curve, &dpp->pkex_private, + &dpp->pkex_public)) + goto failed; + + /* + * "If Qi is the point-at-infinity, the code shall be deleted and the + * user should be notified to provision a new code" + */ + qi = dpp_derive_qi(dpp->curve, dpp->pkex_key, dpp->pkex_id, + netdev_get_address(dpp->netdev)); + if (!qi || l_ecc_point_is_infinity(qi)) { + l_debug("Cannot derive Qi, provision a new code"); + goto failed; + } + + dpp->pkex_m = l_ecc_point_new(dpp->curve); + + if (!l_ecc_point_add(dpp->pkex_m, dpp->pkex_public, qi)) + goto failed; + + /* + * If the PKEX fails its probably best to continue with periodic scans + * just in case there is an available network. + */ + if (station) { + dpp->station_autoconnecting = station_get_autoconnect(station); + station_set_autoconnect(station, false); + } + + dpp_pkex_property_changed_notify(dpp); + scan_periodic_stop(dpp->wdev_id); + + dpp->freqs = dpp_default_freqs(dpp, &dpp->freqs_len); + if (!dpp->freqs) + goto failed; + + dpp->current_freq = dpp->freqs[dpp->freqs_idx]; + + dpp_reset_protocol_timer(dpp, DPP_PKEX_PROTO_TIMEOUT); + + l_debug("PKEX start enrollee (id=%s)", dpp->pkex_id ?: "unset"); + + dpp_start_offchannel(dpp, dpp->current_freq); + + return true; + +failed: + dpp_reset(dpp); + return false; +} + +static bool dpp_parse_pkex_args(struct l_dbus_message *message, + const char **key_out, + const char **id_out) +{ + struct l_dbus_message_iter iter; + struct l_dbus_message_iter variant; + const char *dict_key; + const char *key = NULL; + const char *id = NULL; + + if (!l_dbus_message_get_arguments(message, "a{sv}", &iter)) + return false; + + while (l_dbus_message_iter_next_entry(&iter, &dict_key, &variant)) { + if (!strcmp(dict_key, "Code")) { + if (!l_dbus_message_iter_get_variant(&variant, "s", + &key)) + return false; + } else if (!strcmp(dict_key, "Identifier")) { + if (!l_dbus_message_iter_get_variant(&variant, "s", + &id)) + return false; + } + } + + if (!key) + return false; + + + if (id && !dpp_check_pkex_identifier(id)) + return false; + + *key_out = key; + *id_out = id; + + return true; +} + +static struct l_dbus_message *dpp_dbus_pkex_start_enrollee(struct l_dbus *dbus, + struct l_dbus_message *message, + void *user_data) +{ + struct dpp_sm *dpp = user_data; + const char *key; + const char *id; + struct station *station = station_find(netdev_get_ifindex(dpp->netdev)); + + l_debug(""); + + if (dpp->state != DPP_STATE_NOTHING) + return dbus_error_busy(message); + + if (station_get_connected_network(station)) + return dbus_error_busy(message); + + if (!dpp_parse_pkex_args(message, &key, &id)) + goto invalid_args; + + if (!dpp_start_pkex_enrollee(dpp, key, id)) + goto invalid_args; + + return l_dbus_message_new_method_return(message); + +invalid_args: + return dbus_error_invalid_args(message); +} + static void dpp_setup_interface(struct l_dbus_interface *interface) { l_dbus_interface_method(interface, "StartEnrollee", 0, @@ -2734,6 +3495,18 @@ static void dpp_setup_interface(struct l_dbus_interface *interface) l_dbus_interface_property(interface, "URI", 0, "s", dpp_get_uri, NULL); } +static void dpp_setup_pkex_interface(struct l_dbus_interface *interface) +{ + l_dbus_interface_method(interface, "StartEnrollee", 0, + dpp_dbus_pkex_start_enrollee, "", "a{sv}", "args"); + l_dbus_interface_method(interface, "Stop", 0, dpp_dbus_stop, "", ""); + + l_dbus_interface_property(interface, "Started", 0, "b", + dpp_pkex_get_started, NULL); + l_dbus_interface_property(interface, "Role", 0, "s", dpp_get_role, + NULL); +} + static void dpp_destroy_interface(void *user_data) { struct dpp_sm *dpp = user_data; @@ -2756,6 +3529,10 @@ static int dpp_init(void) l_dbus_register_interface(dbus_get_bus(), IWD_DPP_INTERFACE, dpp_setup_interface, dpp_destroy_interface, false); + /* No destroy since DPP/PKEX interfaces are added/removed together */ + l_dbus_register_interface(dbus_get_bus(), IWD_DPP_PKEX_INTERFACE, + dpp_setup_pkex_interface, + NULL, false); mlme_watch = l_genl_family_register(nl80211, "mlme", dpp_mlme_notify, NULL, NULL); From patchwork Thu Oct 26 20:26:57 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: James Prestwood X-Patchwork-Id: 13437870 Received: from mail-qk1-f169.google.com (mail-qk1-f169.google.com [209.85.222.169]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 56B253D38A for ; Thu, 26 Oct 2023 20:27:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="TEp1AEPB" Received: by mail-qk1-f169.google.com with SMTP id af79cd13be357-7781bc3783fso101994685a.1 for ; Thu, 26 Oct 2023 13:27:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1698352051; x=1698956851; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=n8CnrDKBbx9sihJOY2efilyx7ZI/5yJv4QQacBYedpg=; b=TEp1AEPBdBe4pZqQ1NMH7FcS+r8rTpw34/eq13JAEu95e2LrMjPfXUi1yBPYNWpg5e 3xNgSVEMeaQbVfkZMwItgVr1xC6MXqLxoML+ZDNjREb2bDr74E4v1x/m/JaLIU2dgAoL 5189B0edQViVPMuha0w506zwgbu1NMXaNpgRRzh2IT+yjFfzgwpHwYfxcqmQGIcLBxtO 3kdyWjsAC+MZynU5FzcfyJk1qrYsQyZgPC83qif3k2DEJNW9RLP6ISMcSa/5qBiDTsaN 4ffXRgU9jgn+rQHIdkEDkHUaUSkbXTsi3tfoZr5CYiQdnvskNPLdTJiRdedJTnp2H7IV xyNg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698352051; x=1698956851; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=n8CnrDKBbx9sihJOY2efilyx7ZI/5yJv4QQacBYedpg=; b=H6Ma0iy4sqz9zgbXlkIGEmPb64iR5+Qn/ZYNCBBX9h4o/koilCbIbAbhmtoLM/04w4 4WTSvsr6C0RUWwn175tAxD3mKcnTQLnM+78lyE3PupcQhPb6DH2cVF5JS0CyYe8TT3L2 +KAAKGo4W42sNU796veU2Ihuq1FU2z0W3pzGhyTXaIJS8vsZdCEe82wKPRD8Nc7Jzk+z vXryclUMeTVqK9DyPXstKU144vB8enQ32PxJHHQY1atIdSHZutRgDeoeupgXpeqdMCTZ Q4Uwhl2UbhwBBu6zu3WVrfg591rCu0nn01O+TK+p4Ps7mXS4U++F2fdsr2K4zCqIQKqG AATg== X-Gm-Message-State: AOJu0YzPGj808NOeuv+KCc+4LX/IK9D/PdVi7PNEtIroVMWkBM5osr8w GNaksFEv2e7ZAiRSCJAH3RHXz6arQ38= X-Google-Smtp-Source: AGHT+IFze2m+eue/mzAJuff+UVU7reSskDWH1u29K9fHUbTrCKpDJxWJDJUcBW52MnA4QA46W0EjHw== X-Received: by 2002:a05:620a:2717:b0:77a:2ff:779b with SMTP id b23-20020a05620a271700b0077a02ff779bmr432811qkp.21.1698352051058; Thu, 26 Oct 2023 13:27:31 -0700 (PDT) Received: from LOCLAP699.rst-02.locus (50-78-19-50-static.hfc.comcastbusiness.net. [50.78.19.50]) by smtp.gmail.com with ESMTPSA id r4-20020a05620a298400b007742c2ad7dfsm7303qkp.73.2023.10.26.13.27.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 26 Oct 2023 13:27:30 -0700 (PDT) From: James Prestwood To: iwd@lists.linux.dev Cc: James Prestwood Subject: [PATCH v2 15/15] dpp: initial version of PKEX configurator support Date: Thu, 26 Oct 2023 13:26:57 -0700 Message-Id: <20231026202657.183591-16-prestwoj@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231026202657.183591-1-prestwoj@gmail.com> References: <20231026202657.183591-1-prestwoj@gmail.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The PKEX configurator role is currently limited to being a responder. When started the configurator will listen on its current operating channel for a PKEX exchange request. Once received it and the encrypted key is properly decrypted it treats this peer as the enrollee and won't allow configurations from other peers unless PKEX is restarted. The configurator will encrypt and send its encrypted ephemeral key in the PKEX exchange response. The enrollee then sends its encrypted bootstrapping key (as commit-reveal request) then the same for the configurator (as commit-reveal response). After this, PKEX authentication begins. The enrollee is expected to send the authenticate request, since its the initiator. --- src/dpp.c | 596 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 595 insertions(+), 1 deletion(-) diff --git a/src/dpp.c b/src/dpp.c index 9d99cd50..3e3fb541 100644 --- a/src/dpp.c +++ b/src/dpp.c @@ -152,9 +152,12 @@ struct dpp_sm { struct l_dbus_message *pending; /* PKEX-specific values */ + uint32_t agent_id; + char *agent_path; char *pkex_id; char *pkex_key; uint8_t pkex_version; + struct l_ecc_point *peer_encr_key; struct l_ecc_point *pkex_m; /* Ephemeral key Y' or X' for enrollee or configurator */ struct l_ecc_point *y_or_x; @@ -353,12 +356,21 @@ static void dpp_free_auth_data(struct dpp_sm *dpp) dpp->pkex_private = NULL; } + if (dpp->peer_encr_key) { + l_ecc_point_free(dpp->peer_encr_key); + dpp->peer_encr_key = NULL; + } } static void dpp_reset(struct dpp_sm *dpp) { struct station *station = station_find(netdev_get_ifindex(dpp->netdev)); + if (dpp->agent_id) { + agent_request_cancel(dpp->agent_id, -ESHUTDOWN); + dpp->agent_id = 0; + } + if (dpp->uri) { l_free(dpp->uri); dpp->uri = NULL; @@ -1849,7 +1861,8 @@ static void authenticate_request(struct dpp_sm *dpp, const uint8_t *from, if (util_is_broadcast_address(from)) return; - if (dpp->state != DPP_STATE_PRESENCE) + if (dpp->state != DPP_STATE_PRESENCE && + dpp->state != DPP_STATE_AUTHENTICATING) return; l_debug("authenticate request"); @@ -2709,6 +2722,493 @@ failed: dpp_reset(dpp); } +static void dpp_send_bad_group(struct dpp_sm *dpp, const uint8_t *addr) +{ + uint8_t hdr[32]; + uint8_t attrs[256]; + uint8_t *ptr = attrs; + uint16_t group; + uint8_t status = DPP_STATUS_BAD_GROUP; + struct iovec iov[2]; + const uint8_t *own_mac = netdev_get_address(dpp->netdev); + + l_put_le16(l_ecc_curve_get_ike_group(dpp->curve), &group); + + iov[0].iov_len = dpp_build_header(own_mac, addr, + DPP_FRAME_PKEX_XCHG_RESPONSE, hdr); + iov[0].iov_base = hdr; + + ptr += dpp_append_attr(ptr, DPP_ATTR_STATUS, &status, 1); + ptr += dpp_append_attr(ptr, DPP_ATTR_PROTOCOL_VERSION, + &dpp->pkex_version, 1); + ptr += dpp_append_attr(ptr, DPP_ATTR_FINITE_CYCLIC_GROUP, &group, 2); + + iov[1].iov_base = attrs; + iov[1].iov_len = ptr - attrs; + + dpp_send_frame(dpp, iov, 2, dpp->current_freq); +} + +static void dpp_send_bad_code(struct dpp_sm *dpp, const uint8_t *addr) +{ + uint8_t hdr[32]; + uint8_t attrs[256]; + uint8_t *ptr = attrs; + uint8_t status = DPP_STATUS_BAD_CODE; + struct iovec iov[2]; + const uint8_t *own_mac = netdev_get_address(dpp->netdev); + + iov[0].iov_len = dpp_build_header(own_mac, addr, + DPP_FRAME_PKEX_XCHG_RESPONSE, hdr); + iov[0].iov_base = hdr; + + ptr += dpp_append_attr(ptr, DPP_ATTR_STATUS, &status, 1); + ptr += dpp_append_attr(ptr, DPP_ATTR_PROTOCOL_VERSION, + &dpp->pkex_version, 1); + if (dpp->pkex_id) + ptr += dpp_append_attr(ptr, DPP_ATTR_CODE_IDENTIFIER, + dpp->pkex_id, strlen(dpp->pkex_id)); + + iov[1].iov_base = attrs; + iov[1].iov_len = ptr - attrs; + + dpp_send_frame(dpp, iov, 2, dpp->current_freq); +} + +static void dpp_send_pkex_exchange_response(struct dpp_sm *dpp, + struct l_ecc_point *n) +{ + uint8_t hdr[32]; + uint8_t attrs[256]; + uint8_t *ptr = attrs; + uint64_t n_data[L_ECC_MAX_DIGITS * 2]; + uint16_t group; + uint8_t status = DPP_STATUS_OK; + struct iovec iov[2]; + const uint8_t *own_mac = netdev_get_address(dpp->netdev); + + l_put_le16(l_ecc_curve_get_ike_group(dpp->curve), &group); + + iov[0].iov_len = dpp_build_header(own_mac, dpp->peer_addr, + DPP_FRAME_PKEX_XCHG_RESPONSE, hdr); + iov[0].iov_base = hdr; + + ptr += dpp_append_attr(ptr, DPP_ATTR_STATUS, &status, 1); + + if (dpp->pkex_id) + ptr += dpp_append_attr(ptr, DPP_ATTR_CODE_IDENTIFIER, + dpp->pkex_id, strlen(dpp->pkex_id)); + + l_ecc_point_get_data(n, n_data, sizeof(n_data)); + + ptr += dpp_append_attr(ptr, DPP_ATTR_ENCRYPTED_KEY, + n_data, dpp->key_len * 2); + + iov[1].iov_base = attrs; + iov[1].iov_len = ptr - attrs; + + dpp->state = DPP_STATE_PKEX_COMMIT_REVEAL; + + dpp_pkex_property_changed_notify(dpp); + + dpp_send_frame(dpp, iov, 2, dpp->current_freq); +} + +static void dpp_process_pkex_exchange_request(struct dpp_sm *dpp, + struct l_ecc_point *m) +{ + _auto_(l_ecc_point_free) struct l_ecc_point *n = NULL; + _auto_(l_ecc_point_free) struct l_ecc_point *qr = NULL; + _auto_(l_ecc_point_free) struct l_ecc_point *qi = NULL; + _auto_(l_ecc_point_free) struct l_ecc_point *k = NULL; + const uint8_t *own_addr = netdev_get_address(dpp->netdev); + + /* Qi = H(MAC-Initiator | [identifier | ] code) * Pi */ + qi = dpp_derive_qi(dpp->curve, dpp->pkex_key, dpp->pkex_id, + dpp->peer_addr); + if (!qi) { + l_debug("could not derive Qi"); + return; + } + + /* X' = M - Qi */ + dpp->y_or_x = l_ecc_point_new(dpp->curve); + + l_ecc_point_inverse(qi); + l_ecc_point_add(dpp->y_or_x, m, qi); + + /* + * "The resulting ephemeral key, denoted X’, is checked whether it is + * the point-at-infinity. If it is not valid, the protocol silently + * fails" + */ + if (l_ecc_point_is_infinity(dpp->y_or_x)) { + l_debug("X' is at infinity, ignore message"); + dpp_reset(dpp); + return; + } + + qr = dpp_derive_qr(dpp->curve, dpp->pkex_key, dpp->pkex_id, own_addr); + if (!qr || l_ecc_point_is_infinity(qr)) { + l_debug("Qr did not derive"); + l_ecc_point_free(dpp->y_or_x); + dpp->y_or_x = NULL; + goto bad_code; + } + + /* + * "The Responder then generates a random ephemeral keypair, y/Y, + * encrypts Y with Qr to obtain the result, denoted N." + */ + l_ecdh_generate_key_pair(dpp->curve, &dpp->pkex_private, + &dpp->pkex_public); + + /* N = Y + Qr */ + n = l_ecc_point_new(dpp->curve); + + l_ecc_point_add(n, dpp->pkex_public, qr); + + /* K = y * X' */ + + k = l_ecc_point_new(dpp->curve); + + l_ecc_point_multiply(k, dpp->pkex_private, dpp->y_or_x); + + /* z = HKDF(<>, info | M.x | N.x | code, K.x) */ + dpp_derive_z(dpp->peer_addr, own_addr, n, m, k, dpp->pkex_key, + dpp->pkex_id, dpp->z, &dpp->z_len); + + dpp_send_pkex_exchange_response(dpp, n); + + return; + +bad_code: + dpp_send_bad_code(dpp, dpp->peer_addr); + return; +} + +static void dpp_agent_request_cb(enum agent_result result, + const char *code, + struct l_dbus_message *message, + void *user_data) +{ + struct dpp_sm *dpp = user_data; + + l_debug("agent replied with result %u", result); + + if (result != AGENT_RESULT_OK) + goto failed; + + dpp->pkex_key = l_strdup(code); + + dpp_process_pkex_exchange_request(dpp, dpp->peer_encr_key); + + return; + +failed: + l_debug("Failed to obtain code for identifier %s", dpp->pkex_id); + dpp_reset(dpp); +} + +static void dpp_agent_request_destroy(void *user_data) +{ + struct dpp_sm *dpp = user_data; + + dpp->agent_id = 0; +} + +static bool dpp_request_code(struct dpp_sm *dpp, const char *identifier) +{ + dpp->agent_id = agent_request_user_password( + dpp->agent_path, + identifier, dpp_agent_request_cb, NULL, + dpp, dpp_agent_request_destroy); + return dpp->agent_id != 0; +} + +static void dpp_handle_pkex_exchange_request(struct dpp_sm *dpp, + const uint8_t *from, + const uint8_t *body, size_t body_len) +{ + struct dpp_attr_iter iter; + enum dpp_attribute_type type; + size_t len; + const uint8_t *data; + uint8_t version = 0; + uint16_t group = 0; + const char *id = NULL; + size_t id_len = 0; + const void *key = NULL; + size_t key_len = 0; + _auto_(l_ecc_point_free) struct l_ecc_point *m = NULL; + + l_debug("PKEX exchange request "MAC, MAC_STR(from)); + + if (dpp->state != DPP_STATE_PKEX_EXCHANGE) + return; + + if (dpp->role != DPP_CAPABILITY_CONFIGURATOR) + return; + + dpp_attr_iter_init(&iter, body + 8, body_len - 8); + + while (dpp_attr_iter_next(&iter, &type, &len, &data)) { + switch (type) { + case DPP_ATTR_PROTOCOL_VERSION: + if (len != 1) + return; + + version = l_get_u8(data); + break; + case DPP_ATTR_FINITE_CYCLIC_GROUP: + if (len != 2) + return; + + group = l_get_le16(data); + break; + case DPP_ATTR_CODE_IDENTIFIER: + id = (char *) data; + id_len = len; + break; + case DPP_ATTR_ENCRYPTED_KEY: + key = data; + key_len = len; + break; + default: + break; + } + } + + if (!key || !group) { + l_debug("initiator did not provide group or key, ignoring"); + return; + } + + if (group != l_ecc_curve_get_ike_group(dpp->curve)) { + l_debug("initiator is not using the same group"); + goto bad_group; + } + + /* + * If the group isn't the same the key length won't match, so check + * this here after we've determined the groups are equal + */ + if (key_len != dpp->key_len * 2) { + l_debug("Unexpected encrypted key length"); + return; + } + + if (version && version != dpp->pkex_version) { + l_debug("initiator is not using the same version, ignoring"); + return; + } + + if (dpp->pkex_id) { + if (!id || !dpp_check_pkex_identifier(id) || + id_len != strlen(dpp->pkex_id) || + strncmp(dpp->pkex_id, id, id_len)) { + l_debug("mismatch identifier, ignoring"); + return; + } + } + + m = l_ecc_point_from_data(dpp->curve, L_ECC_POINT_TYPE_FULL, + key, key_len); + if (!m) { + l_debug("could not parse key from initiator, ignoring"); + return; + } + + memcpy(dpp->peer_addr, from, 6); + + if (!dpp->pkex_key) { + if (!id) { + l_debug("Configurator started with agent but enrollee " + "sent no identifier, ignoring"); + return; + } + + dpp->pkex_id = l_strndup(id, id_len); + + /* Need to obtain code from agent */ + if (!dpp_request_code(dpp, dpp->pkex_id)) { + l_debug("Failed to request code from agent!"); + return; + } + + /* Save the encrypted key/identifier for the agent callback */ + + dpp->peer_encr_key = l_steal_ptr(m); + + return; + } + + dpp_process_pkex_exchange_request(dpp, m); + + return; + +bad_group: + dpp_send_bad_group(dpp, from); +} + +static void dpp_send_commit_reveal_response(struct dpp_sm *dpp, + const uint8_t *v, size_t v_len) +{ + uint8_t hdr[32]; + uint8_t attrs[256]; + uint8_t *ptr = attrs; + uint8_t one = 1; + struct iovec iov[2]; + const uint8_t *own_mac = netdev_get_address(dpp->netdev); + uint8_t b_pub[L_ECC_POINT_MAX_BYTES]; + size_t b_len; + + b_len = l_ecc_point_get_data(dpp->boot_public, b_pub, sizeof(b_pub)); + + + iov[0].iov_len = dpp_build_header(own_mac, dpp->peer_addr, + DPP_FRAME_PKEX_COMMIT_REVEAL_RESPONSE, hdr); + iov[0].iov_base = hdr; + + ptr += dpp_append_wrapped_data(hdr + 26, 6, &one, 1, ptr, + sizeof(attrs), dpp->z, dpp->z_len, 2, + DPP_ATTR_BOOTSTRAPPING_KEY, b_len, b_pub, + DPP_ATTR_RESPONDER_AUTH_TAG, v_len, v); + + iov[1].iov_base = attrs; + iov[1].iov_len = ptr - attrs; + + dpp_send_frame(dpp, iov, 2, dpp->current_freq); +} + +static void dpp_handle_pkex_commit_reveal_request(struct dpp_sm *dpp, + const uint8_t *from, + const uint8_t *body, size_t body_len) +{ + struct dpp_attr_iter iter; + enum dpp_attribute_type type; + size_t len; + const uint8_t *data; + const void *wrapped = NULL; + size_t wrapped_len = 0; + _auto_(l_free) uint8_t *unwrapped = NULL; + size_t unwrapped_len; + uint8_t zero = 0; + const void *key = 0; + size_t key_len = 0; + const void *i_auth = NULL; + size_t i_auth_len = 0; + _auto_(l_ecc_point_free) struct l_ecc_point *a = NULL; + _auto_(l_ecc_point_free) struct l_ecc_point *j = NULL; + _auto_(l_ecc_point_free) struct l_ecc_point *l = NULL; + uint8_t u[L_ECC_SCALAR_MAX_BYTES]; + size_t u_len = 0; + uint8_t v[L_ECC_SCALAR_MAX_BYTES]; + size_t v_len = 0; + const uint8_t *own_addr = netdev_get_address(dpp->netdev); + + l_debug("PKEX commit-reveal request "MAC, MAC_STR(from)); + + if (dpp->state != DPP_STATE_PKEX_COMMIT_REVEAL) + return; + + if (dpp->role != DPP_CAPABILITY_CONFIGURATOR) + return; + + dpp_attr_iter_init(&iter, body + 8, body_len - 8); + + while (dpp_attr_iter_next(&iter, &type, &len, &data)) { + switch (type) { + case DPP_ATTR_WRAPPED_DATA: + wrapped = data; + wrapped_len = len; + break; + default: + break; + } + } + + if (!wrapped) { + l_debug("No wrapped data"); + return; + } + + unwrapped = dpp_unwrap_attr(body + 2, 6, &zero, 1, dpp->z, dpp->z_len, + wrapped, wrapped_len, &unwrapped_len); + if (!unwrapped) { + l_debug("Failed to unwrap attributes"); + return; + } + + dpp_attr_iter_init(&iter, unwrapped, unwrapped_len); + + while (dpp_attr_iter_next(&iter, &type, &len, &data)) { + switch (type) { + case DPP_ATTR_BOOTSTRAPPING_KEY: + if (len != dpp->key_len * 2) + return; + + key = data; + key_len = len; + break; + case DPP_ATTR_INITIATOR_AUTH_TAG: + if (len != 32) + return; + + i_auth = data; + i_auth_len = len; + break; + default: + break; + } + } + + if (!key || !i_auth) { + l_debug("missing attributes"); + return; + } + + dpp->peer_boot_public = l_ecc_point_from_data(dpp->curve, + L_ECC_POINT_TYPE_FULL, key, key_len); + if (!dpp->peer_boot_public) { + l_debug("peers boostrapping key did not validate"); + goto failed; + } + + /* J' = y * A' */ + j = l_ecc_point_new(dpp->curve); + + l_ecc_point_multiply(j, dpp->pkex_private, dpp->peer_boot_public); + + dpp_derive_u(j, dpp->peer_addr, dpp->peer_boot_public, dpp->pkex_public, + dpp->y_or_x, u, &u_len); + + if (memcmp(u, i_auth, i_auth_len)) { + l_debug("Initiator auth tag did not verify"); + goto failed; + } + + /* L' = x * B' */ + l = l_ecc_point_new(dpp->curve); + + l_ecc_point_multiply(l, dpp->boot_private, dpp->y_or_x); + + if (!dpp_derive_v(l, own_addr, dpp->boot_public, dpp->y_or_x, + dpp->pkex_public, v, &v_len)) { + l_debug("Failed to derive v"); + goto failed; + } + + dpp_send_commit_reveal_response(dpp, v, v_len); + + dpp_pkex_start_authentication(dpp); + + return; + +failed: + dpp_reset(dpp); +} + static void dpp_handle_frame(struct dpp_sm *dpp, const struct mmpdu_header *frame, const void *body, size_t body_len) @@ -2751,6 +3251,14 @@ static void dpp_handle_frame(struct dpp_sm *dpp, dpp_handle_pkex_commit_reveal_response(dpp, frame->address_2, body, body_len); break; + case DPP_FRAME_PKEX_VERSION1_XCHG_REQUST: + dpp_handle_pkex_exchange_request(dpp, frame->address_2, body, + body_len); + break; + case DPP_FRAME_PKEX_COMMIT_REVEAL_REQUEST: + dpp_handle_pkex_commit_reveal_request(dpp, frame->address_2, + body, body_len); + break; default: l_debug("Unhandled DPP frame %u", *ptr); break; @@ -3477,6 +3985,88 @@ invalid_args: return dbus_error_invalid_args(message); } +static struct l_dbus_message *dpp_start_pkex_configurator(struct dpp_sm *dpp, + const char *key, const char *identifier, + struct l_dbus_message *message) +{ + struct handshake_state *hs = netdev_get_handshake(dpp->netdev); + struct station *station = station_find(netdev_get_ifindex(dpp->netdev)); + struct network *network = station_get_connected_network(station); + struct scan_bss *bss = station_get_connected_bss(station); + const struct l_settings *settings; + + if (dpp->state != DPP_STATE_NOTHING) + return dbus_error_busy(message); + + if (!network || !bss) + return dbus_error_not_connected(message); + + settings = network_get_settings(network); + if (!settings) { + l_debug("No settings for network, is this a known network?"); + return dbus_error_not_configured(message); + } + + if (identifier) + dpp->pkex_id = l_strdup(identifier); + + if (key) + dpp->pkex_key = l_strdup(key); + + dpp->role = DPP_CAPABILITY_CONFIGURATOR; + dpp->state = DPP_STATE_PKEX_EXCHANGE; + dpp->current_freq = bss->frequency; + dpp->pkex_version = 1; + dpp->config = dpp_configuration_new(network_get_settings(network), + network_get_ssid(network), + hs->akm_suite); + + dpp_reset_protocol_timer(dpp, DPP_PKEX_PROTO_TIMEOUT); + dpp_pkex_property_changed_notify(dpp); + + if (dpp->pkex_key) + l_debug("Starting PKEX configurator for single enrollee"); + else + l_debug("Starting PKEX configurator with agent"); + + return l_dbus_message_new_method_return(message); +} + +static struct l_dbus_message *dpp_dbus_pkex_configure_enrollee( + struct l_dbus *dbus, + struct l_dbus_message *message, + void *user_data) +{ + struct dpp_sm *dpp = user_data; + const char *key; + const char *id; + + l_debug(""); + + if (!dpp_parse_pkex_args(message, &key, &id)) + return dbus_error_invalid_args(message); + + return dpp_start_pkex_configurator(dpp, key, id, message); +} + +static struct l_dbus_message *dpp_dbus_pkex_start_configurator( + struct l_dbus *dbus, + struct l_dbus_message *message, + void *user_data) +{ + struct dpp_sm *dpp = user_data; + const char *path; + + if (!l_dbus_message_get_arguments(message, "o", &path)) { + l_debug("Could not get agent path"); + return dbus_error_invalid_args(message); + } + + dpp->agent_path = l_strdup(path); + + return dpp_start_pkex_configurator(dpp, NULL, NULL, message); +} + static void dpp_setup_interface(struct l_dbus_interface *interface) { l_dbus_interface_method(interface, "StartEnrollee", 0, @@ -3499,6 +4089,10 @@ static void dpp_setup_pkex_interface(struct l_dbus_interface *interface) { l_dbus_interface_method(interface, "StartEnrollee", 0, dpp_dbus_pkex_start_enrollee, "", "a{sv}", "args"); + l_dbus_interface_method(interface, "ConfigureEnrollee", 0, + dpp_dbus_pkex_configure_enrollee, "", "a{sv}", "args"); + l_dbus_interface_method(interface, "StartConfigurator", 0, + dpp_dbus_pkex_start_configurator, "", "o", "path"); l_dbus_interface_method(interface, "Stop", 0, dpp_dbus_stop, "", ""); l_dbus_interface_property(interface, "Started", 0, "b",