From patchwork Wed Mar 13 17:13:07 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Prestwood X-Patchwork-Id: 13591630 Received: from mail-ot1-f46.google.com (mail-ot1-f46.google.com [209.85.210.46]) (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 AA0F56167C for ; Wed, 13 Mar 2024 17:13:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1710350019; cv=none; b=tLodqfiikEnIZW4+wREYgPNs8If+Tn6fS5dbRj3zBv/aPJad3+feAlpZvqRlK93Oxxeo0Zipw5Bw9u/RissERQ6sLKXzNtWEr0tDRum+LG6GVDE1sqJY1/t8b54ZNMel91iRLi08wFtf1ExNU8rS2rvz5vAw+2CCRdFxa2TnkG4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1710350019; c=relaxed/simple; bh=jJ5esnnRNgXe3z3MIu5zboM+GnUmYAxAdp1sy3EHfXo=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=vBrTMqaqvnSp54DMEyr/X1+rUz2HecyPNBV2x5cT9VNTeuBtMlcj4tVfQXZdnsKGtkIUKBQJwV9gxXLIeILVeKJRMxx/jBpMswQIjy2sHDQavSBXJzaxmMs87PY5RME+PVAuqRPz687e2BqDaeM56fRNPqY7afdgrfIIGewBGH4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=iRoTaYOk; arc=none smtp.client-ip=209.85.210.46 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="iRoTaYOk" Received: by mail-ot1-f46.google.com with SMTP id 46e09a7af769-6e4fb3a2687so454277a34.3 for ; Wed, 13 Mar 2024 10:13:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1710350016; x=1710954816; 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=4JYrgMBb05/WBhrrCym7IMqYhMQgQYQ/GI1tbANiwLc=; b=iRoTaYOkIHorAhK8xvHzjSqHqMwfNbEe+dRrMY638MNvKhGEfxDLPgGdU5fPOi64cw +s7mbRV/y3LlpTjdROC74NY47uugbUiguSqZCiEa3Ufzy/x7yJtOG/spwK43H7cl6Bzr Oh4KYjuaMSGovLGeB56ueqJI9qqttk4MJ2jClrqDpq1UIGGNZ8hVHd/TAUN3hMW9skiq eZQRL4YW6JIjnk1VWO+urKwCykVmkAm1pb+Y1DntkZr1/Y+3sJOEDVmTG6mMweEiAtJO FNAvgTwhI6852+DE9wmjP1gST4GBTs0+PVsAaSA9t3DiprXUykF9toJ1P7+IzvCBmHfs 2vtQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1710350016; x=1710954816; 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=4JYrgMBb05/WBhrrCym7IMqYhMQgQYQ/GI1tbANiwLc=; b=USTnEME4LcL4wM8MmkB4wVHX3NkUJS2ayYpjl8pnJ4h93nA7wRhVDwT3nfmguu4b97 GjwSw3Z3iBUfM6viQKuZzkgQQa5h4l7fXDNAe5JZLw5bOHeV3dov4Ut7d8F9yiICqfTd u8+7si92U/C1J3sqFrKa4Z5WMzP9olmyi/AjVIQHG0dSGAhadnj1LgAmldwWfb0WHus4 jxd4Aia9UztvJvIAAJJjaherFc4ciFMMR7W7ll6lGOsG+QDv07zSZ/sUJSz37sZWPtA+ oPFkqD2XjcuNRGPfIYLvw8EVnUucgK+Wnwb8qP7qvHl4Ua/4IijY2jXOdBcoD3L21Nar yFZA== X-Gm-Message-State: AOJu0YxYHgdIUjmvCiyjxj9HpXtjo25KhEsbMGcChoGLXTTRAIzZTsgu +Daq6NuA42Dc7yHCVdErkwIKGNrszTsC0t5Rxm4Tv8ixerwhTAJncGVGKSAD X-Google-Smtp-Source: AGHT+IGC28zFWJtXwEhVNGElz+nyyWgMDekSKztWCZWzqxrxAxiGfwoit9vnIbV3uY1jMJZurvE3HQ== X-Received: by 2002:a9d:7492:0:b0:6e4:e71c:e60f with SMTP id t18-20020a9d7492000000b006e4e71ce60fmr584058otk.12.1710350016202; Wed, 13 Mar 2024 10:13:36 -0700 (PDT) Received: from LOCLAP699.rst-01.locus ([208.195.13.130]) by smtp.gmail.com with ESMTPSA id i4-20020ae9ee04000000b007882e204d45sm4927136qkg.37.2024.03.13.10.13.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 13 Mar 2024 10:13:35 -0700 (PDT) From: James Prestwood To: iwd@lists.linux.dev Cc: James Prestwood Subject: [RFC 1/5] dpp: prep for moving AAD within dpp_append_wrapped_data Date: Wed, 13 Mar 2024 10:13:07 -0700 Message-Id: <20240313171311.695830-2-prestwoj@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240313171311.695830-1-prestwoj@gmail.com> References: <20240313171311.695830-1-prestwoj@gmail.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The AAD pointers for DPP are specific to the frame type. This is currently sorted out by the caller within the respective frame building functions but its quite unreadable. There are some comments but lots of magic numbers. This should be moved within the dpp_append_wrapped_data utility but the first step is to make the frame buffer continuous. This will allow the entire frame to be passed and dpp_append_wrapped_data can calculate the AAD offsets itself. --- src/dpp.c | 239 +++++++++++++++++++++++++----------------------------- 1 file changed, 112 insertions(+), 127 deletions(-) diff --git a/src/dpp.c b/src/dpp.c index 567fe8d2..5aac22a7 100644 --- a/src/dpp.c +++ b/src/dpp.c @@ -648,7 +648,7 @@ static void dpp_frame_retry(struct dpp_sm *dpp) static size_t dpp_build_header(const uint8_t *src, const uint8_t *dest, enum dpp_frame_type type, - uint8_t buf[static 32]) + uint8_t *buf) { uint8_t *ptr = buf + 24; @@ -672,7 +672,7 @@ static size_t dpp_build_header(const uint8_t *src, const uint8_t *dest, static size_t dpp_build_config_header(const uint8_t *src, const uint8_t *dest, uint8_t diag_token, - uint8_t buf[static 37]) + uint8_t *buf) { uint8_t *ptr = buf + 24; @@ -753,22 +753,21 @@ static void dpp_configuration_start(struct dpp_sm *dpp, const uint8_t *addr) { const char *json = "{\"name\":\"IWD\",\"wi-fi_tech\":\"infra\"," "\"netRole\":\"sta\"}"; - struct iovec iov[3]; - uint8_t hdr[37]; - uint8_t attrs[512]; + struct iovec iov; + uint8_t frame[512]; size_t json_len = strlen(json); - uint8_t *ptr = attrs; + uint8_t *ptr = frame; + uint8_t *lptr; l_getrandom(&dpp->diag_token, 1); - iov[0].iov_len = dpp_build_config_header( - netdev_get_address(dpp->netdev), - addr, dpp->diag_token, hdr); - iov[0].iov_base = hdr; + ptr += dpp_build_config_header(netdev_get_address(dpp->netdev), + addr, dpp->diag_token, ptr); l_getrandom(dpp->e_nonce, dpp->nonce_len); /* length */ + lptr = ptr; ptr += 2; /* @@ -780,42 +779,39 @@ static void dpp_configuration_start(struct dpp_sm *dpp, const uint8_t *addr) * In this case there is no query request/response fields, nor any * attributes besides wrapped data meaning zero AD components. */ - ptr += dpp_append_wrapped_data(NULL, 0, NULL, 0, ptr, sizeof(attrs), + ptr += dpp_append_wrapped_data(NULL, 0, NULL, 0, ptr, sizeof(frame), dpp->ke, dpp->key_len, 2, DPP_ATTR_ENROLLEE_NONCE, dpp->nonce_len, dpp->e_nonce, DPP_ATTR_CONFIGURATION_REQUEST, json_len, json); - l_put_le16(ptr - attrs - 2, attrs); + l_put_le16(ptr - lptr - 2, lptr); - iov[1].iov_base = attrs; - iov[1].iov_len = ptr - attrs; + iov.iov_base = frame; + iov.iov_len = ptr - frame; dpp->state = DPP_STATE_CONFIGURING; - dpp_send_frame(dpp, iov, 2, dpp->current_freq); + dpp_send_frame(dpp, &iov, 1, dpp->current_freq); } static void send_config_result(struct dpp_sm *dpp, const uint8_t *to) { - uint8_t hdr[32]; - struct iovec iov[2]; - uint8_t attrs[256]; - uint8_t *ptr = attrs; + struct iovec iov; + uint8_t frame[256]; + uint8_t *ptr = frame; uint8_t zero = 0; - iov[0].iov_len = dpp_build_header(netdev_get_address(dpp->netdev), to, - DPP_FRAME_CONFIGURATION_RESULT, hdr); - iov[0].iov_base = hdr; - - ptr += dpp_append_wrapped_data(hdr + 26, 6, attrs, 0, ptr, - sizeof(attrs), dpp->ke, dpp->key_len, 2, + ptr += dpp_build_header(netdev_get_address(dpp->netdev), to, + DPP_FRAME_CONFIGURATION_RESULT, ptr); + ptr += dpp_append_wrapped_data(frame + 26, 6, ptr, 0, ptr, + sizeof(frame), dpp->ke, dpp->key_len, 2, DPP_ATTR_STATUS, (size_t) 1, &zero, DPP_ATTR_ENROLLEE_NONCE, dpp->nonce_len, dpp->e_nonce); - iov[1].iov_base = attrs; - iov[1].iov_len = ptr - attrs; + iov.iov_base = frame; + iov.iov_len = ptr - frame; - dpp_send_frame(dpp, iov, 2, dpp->current_freq); + dpp_send_frame(dpp, &iov, 1, dpp->current_freq); } static void dpp_write_config(struct dpp_configuration *config, @@ -1162,18 +1158,20 @@ static void dpp_handle_config_response_frame(const struct mmpdu_header *frame, static void dpp_send_config_response(struct dpp_sm *dpp, uint8_t status) { _auto_(l_free) char *json = NULL; - struct iovec iov[3]; - uint8_t hdr[41]; - uint8_t attrs[512]; + struct iovec iov; + uint8_t frame[512]; size_t json_len; - uint8_t *ptr = hdr + 24; + uint8_t *ptr = frame; + uint8_t *lptr; + + memset(frame, 0, sizeof(frame)); - memset(hdr, 0, sizeof(hdr)); + l_put_le16(0x00d0, ptr); + memcpy(ptr + 4, dpp->peer_addr, 6); + memcpy(ptr + 10, netdev_get_address(dpp->netdev), 6); + memcpy(ptr + 16, broadcast, 6); - l_put_le16(0x00d0, hdr); - memcpy(hdr + 4, dpp->peer_addr, 6); - memcpy(hdr + 10, netdev_get_address(dpp->netdev), 6); - memcpy(hdr + 16, broadcast, 6); + ptr += 24; *ptr++ = 0x04; *ptr++ = 0x0b; @@ -1192,11 +1190,7 @@ static void dpp_send_config_response(struct dpp_sm *dpp, uint8_t status) *ptr++ = 0x1a; *ptr++ = 1; - iov[0].iov_base = hdr; - iov[0].iov_len = ptr - hdr; - - ptr = attrs; - + lptr = ptr; ptr += 2; /* length */ ptr += dpp_append_attr(ptr, DPP_ATTR_STATUS, &status, 1); @@ -1211,26 +1205,26 @@ static void dpp_send_config_response(struct dpp_sm *dpp, uint8_t status) json = dpp_configuration_to_json(dpp->config); json_len = strlen(json); - ptr += dpp_append_wrapped_data(attrs + 2, ptr - attrs - 2, - NULL, 0, ptr, sizeof(attrs), + ptr += dpp_append_wrapped_data(lptr + 2, ptr - lptr - 2, + NULL, 0, ptr, sizeof(frame), dpp->ke, dpp->key_len, 2, DPP_ATTR_ENROLLEE_NONCE, dpp->nonce_len, dpp->e_nonce, DPP_ATTR_CONFIGURATION_OBJECT, json_len, json); } else - ptr += dpp_append_wrapped_data(attrs + 2, ptr - attrs - 2, - NULL, 0, ptr, sizeof(attrs), + ptr += dpp_append_wrapped_data(lptr + 2, ptr - lptr - 2, + NULL, 0, ptr, sizeof(frame), dpp->ke, dpp->key_len, 2, DPP_ATTR_ENROLLEE_NONCE, dpp->nonce_len, dpp->e_nonce); - l_put_le16(ptr - attrs - 2, attrs); + l_put_le16(ptr - lptr - 2, lptr); - iov[1].iov_base = attrs; - iov[1].iov_len = ptr - attrs; + iov.iov_base = frame; + iov.iov_len = ptr - frame; - dpp_send_frame(dpp, iov, 2, dpp->current_freq); + dpp_send_frame(dpp, &iov, 1, dpp->current_freq); } static bool dpp_check_config_header(const uint8_t *ptr) @@ -1498,13 +1492,13 @@ 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[512]; - uint8_t *ptr = attrs; + uint8_t frame[512]; + uint8_t *ptr = frame; + uint8_t *attrs; uint8_t status = DPP_STATUS_OK; uint64_t r_proto_key[L_ECC_MAX_DIGITS * 2]; uint8_t version = 2; - struct iovec iov[3]; + struct iovec iov; uint8_t wrapped2_plaintext[dpp->key_len + 4]; uint8_t wrapped2[dpp->key_len + 16 + 8]; size_t wrapped2_len; @@ -1512,11 +1506,10 @@ static void send_authenticate_response(struct dpp_sm *dpp) l_ecc_point_get_data(dpp->own_proto_public, r_proto_key, sizeof(r_proto_key)); - iov[0].iov_len = dpp_build_header(netdev_get_address(dpp->netdev), + ptr += dpp_build_header(netdev_get_address(dpp->netdev), dpp->peer_addr, - DPP_FRAME_AUTHENTICATION_RESPONSE, hdr); - iov[0].iov_base = hdr; - + DPP_FRAME_AUTHENTICATION_RESPONSE, ptr); + attrs = ptr; 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); @@ -1545,17 +1538,17 @@ static void send_authenticate_response(struct dpp_sm *dpp) wrapped2_len += 16; - ptr += dpp_append_wrapped_data(hdr + 26, 6, attrs, ptr - attrs, - ptr, sizeof(attrs), dpp->k2, dpp->key_len, 4, + ptr += dpp_append_wrapped_data(frame + 26, 6, attrs, ptr - attrs, + ptr, sizeof(frame), dpp->k2, dpp->key_len, 4, DPP_ATTR_RESPONDER_NONCE, dpp->nonce_len, dpp->r_nonce, DPP_ATTR_INITIATOR_NONCE, dpp->nonce_len, dpp->i_nonce, DPP_ATTR_RESPONDER_CAPABILITIES, (size_t) 1, &dpp->role, DPP_ATTR_WRAPPED_DATA, wrapped2_len, wrapped2); - iov[1].iov_base = attrs; - iov[1].iov_len = ptr - attrs; + iov.iov_base = frame; + iov.iov_len = ptr - frame; - dpp_send_frame(dpp, iov, 2, dpp->current_freq); + dpp_send_frame(dpp, &iov, 1, dpp->current_freq); } static void authenticate_confirm(struct dpp_sm *dpp, const uint8_t *from, @@ -1699,34 +1692,33 @@ static void dpp_auth_request_failed(struct dpp_sm *dpp, enum dpp_status status, void *k1) { - uint8_t hdr[32]; - uint8_t attrs[128]; - uint8_t *ptr = attrs; + uint8_t frame[128]; + uint8_t *ptr = frame; + uint8_t *attrs; uint8_t version = 2; uint8_t s = status; - struct iovec iov[2]; + struct iovec iov; - iov[0].iov_len = dpp_build_header(netdev_get_address(dpp->netdev), + ptr += dpp_build_header(netdev_get_address(dpp->netdev), dpp->peer_addr, - DPP_FRAME_AUTHENTICATION_RESPONSE, hdr); - iov[0].iov_base = hdr; - + DPP_FRAME_AUTHENTICATION_RESPONSE, ptr); + attrs = ptr; ptr += dpp_append_attr(ptr, DPP_ATTR_STATUS, &s, 1); ptr += dpp_append_attr(ptr, DPP_ATTR_RESPONDER_BOOT_KEY_HASH, dpp->own_boot_hash, 32); ptr += dpp_append_attr(ptr, DPP_ATTR_PROTOCOL_VERSION, &version, 1); - ptr += dpp_append_wrapped_data(hdr + 26, 6, attrs, ptr - attrs, - ptr, sizeof(attrs) - (ptr - attrs), k1, dpp->key_len, 2, + ptr += dpp_append_wrapped_data(frame + 26, 6, attrs, ptr - attrs, + ptr, sizeof(frame) - (ptr - attrs), k1, dpp->key_len, 2, DPP_ATTR_INITIATOR_NONCE, dpp->nonce_len, dpp->i_nonce, DPP_ATTR_RESPONDER_CAPABILITIES, (size_t) 1, &dpp->role); - iov[1].iov_base = attrs; - iov[1].iov_len = ptr - attrs; + iov.iov_base = frame; + iov.iov_len = ptr - frame; - dpp_send_frame(dpp, iov, 2, dpp->current_freq); + dpp_send_frame(dpp, &iov, 1, dpp->current_freq); } static bool dpp_check_roles(struct dpp_sm *dpp, uint8_t peer_capa) @@ -1771,12 +1763,12 @@ static void dpp_presence_announce(struct dpp_sm *dpp) static bool dpp_send_authenticate_request(struct dpp_sm *dpp) { - uint8_t hdr[32]; - uint8_t attrs[256]; - uint8_t *ptr = attrs; + uint8_t frame[256]; + uint8_t *ptr = frame; + uint8_t *attrs; uint64_t i_proto_key[L_ECC_MAX_DIGITS * 2]; uint8_t version = 2; - struct iovec iov[2]; + struct iovec iov; struct station *station = station_find(netdev_get_ifindex(dpp->netdev)); struct scan_bss *bss = station_get_connected_bss(station); @@ -1789,10 +1781,10 @@ static bool dpp_send_authenticate_request(struct dpp_sm *dpp) l_ecc_point_get_data(dpp->own_proto_public, i_proto_key, sizeof(i_proto_key)); - iov[0].iov_len = dpp_build_header(netdev_get_address(dpp->netdev), + ptr += dpp_build_header(netdev_get_address(dpp->netdev), dpp->peer_addr, - DPP_FRAME_AUTHENTICATION_REQUEST, hdr); - iov[0].iov_base = hdr; + DPP_FRAME_AUTHENTICATION_REQUEST, ptr); + attrs = ptr; ptr += dpp_append_attr(ptr, DPP_ATTR_RESPONDER_BOOT_KEY_HASH, dpp->peer_boot_hash, 32); @@ -1810,16 +1802,16 @@ static bool dpp_send_authenticate_request(struct dpp_sm *dpp) ptr += dpp_append_attr(ptr, DPP_ATTR_CHANNEL, pair, 2); } - ptr += dpp_append_wrapped_data(hdr + 26, 6, attrs, ptr - attrs, - ptr, sizeof(attrs), dpp->k1, dpp->key_len, 2, + ptr += dpp_append_wrapped_data(frame + 26, 6, attrs, ptr - attrs, + ptr, sizeof(frame), dpp->k1, dpp->key_len, 2, DPP_ATTR_INITIATOR_NONCE, dpp->nonce_len, dpp->i_nonce, DPP_ATTR_INITIATOR_CAPABILITIES, (size_t) 1, &dpp->role); - iov[1].iov_base = attrs; - iov[1].iov_len = ptr - attrs; + iov.iov_base = frame; + iov.iov_len = ptr - frame; - dpp_send_frame(dpp, iov, 2, dpp->current_freq); + dpp_send_frame(dpp, &iov, 1, dpp->current_freq); return true; } @@ -1862,31 +1854,28 @@ static void dpp_send_pkex_exchange_request(struct dpp_sm *dpp) 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; + struct iovec iov; + uint8_t frame[512]; + uint8_t *ptr = frame; 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), + ptr += 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, + ptr); + ptr += dpp_append_wrapped_data(frame + 26, 6, &zero, 1, ptr, + sizeof(frame), 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; + iov.iov_base = frame; + iov.iov_len = ptr - frame; - dpp_send_frame(dpp, iov, 2, dpp->current_freq); + dpp_send_frame(dpp, &iov, 1, dpp->current_freq); } static void dpp_roc_started(void *user_data) @@ -2272,17 +2261,16 @@ auth_request_failed: static void dpp_send_authenticate_confirm(struct dpp_sm *dpp) { - uint8_t hdr[32]; - struct iovec iov[2]; - uint8_t attrs[256]; - uint8_t *ptr = attrs; + struct iovec iov; + uint8_t frame[256]; + uint8_t *ptr = frame; + uint8_t *attrs; uint8_t zero = 0; - iov[0].iov_len = dpp_build_header(netdev_get_address(dpp->netdev), + ptr += dpp_build_header(netdev_get_address(dpp->netdev), dpp->peer_addr, - DPP_FRAME_AUTHENTICATION_CONFIRM, hdr); - iov[0].iov_base = hdr; - + DPP_FRAME_AUTHENTICATION_CONFIRM, ptr); + attrs = ptr; 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); @@ -2290,15 +2278,15 @@ static void dpp_send_authenticate_confirm(struct dpp_sm *dpp) 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, + ptr += dpp_append_wrapped_data(frame + 26, 6, attrs, ptr - attrs, ptr, + sizeof(frame), dpp->ke, dpp->key_len, 1, DPP_ATTR_INITIATOR_AUTH_TAG, dpp->key_len, dpp->auth_tag); - iov[1].iov_base = attrs; - iov[1].iov_len = ptr - attrs; + iov.iov_base = frame; + iov.iov_len = ptr - frame; - dpp_send_frame(dpp, iov, 2, dpp->current_freq); + dpp_send_frame(dpp, &iov, 1, dpp->current_freq); } static void authenticate_response(struct dpp_sm *dpp, const uint8_t *from, @@ -3311,11 +3299,10 @@ bad_group: 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 frame[256]; + uint8_t *ptr = frame; uint8_t one = 1; - struct iovec iov[2]; + struct iovec iov; const uint8_t *own_mac = netdev_get_address(dpp->netdev); uint8_t b_pub[L_ECC_POINT_MAX_BYTES]; size_t b_len; @@ -3323,19 +3310,17 @@ static void dpp_send_commit_reveal_response(struct dpp_sm *dpp, 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, + ptr += dpp_build_header(own_mac, dpp->peer_addr, + DPP_FRAME_PKEX_COMMIT_REVEAL_RESPONSE, ptr); + ptr += dpp_append_wrapped_data(frame + 26, 6, &one, 1, ptr, + sizeof(frame), 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; + iov.iov_base = frame; + iov.iov_len = ptr - frame; - dpp_send_frame(dpp, iov, 2, dpp->current_freq); + dpp_send_frame(dpp, &iov, 1, dpp->current_freq); } static void dpp_handle_pkex_commit_reveal_request(struct dpp_sm *dpp, From patchwork Wed Mar 13 17:13:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Prestwood X-Patchwork-Id: 13591631 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 DA7C161674 for ; Wed, 13 Mar 2024 17:13:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.175 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1710350021; cv=none; b=givSSLoRvVC2Ko7H7AiaccbZCnOO9cJ7mC0J2hBBtBlhdStaAfjunbHlWvK9V/GIAYzYAW3yPpmKmI9gjuEhKkUULiCcIi/CiZLL/Vb04e/Cumx4qMj8UqNbeZ3wUtrNen/b0JmcY91F1aAnn4pyD1d5fjUgjFMGqj2/LyBgaCM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1710350021; c=relaxed/simple; bh=sFTQKNf5ZO84V2j7VJzumOiE8EsS7sMgoo117zfDSZQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=XehDLPdUsADiRLOGwbGhzSFx5PGSazukWsv6IqLXrJOh0GsNAO5YHMRMZv0Llr/GK5Zs/nEAtqvFRUeRgx1JzKqmtc0Uims306zfUulTA/4kzqMhb1YR27osy+NgOR3ASlW34vIoXWmOmX39wc97rHSvMlVN/OVwSj1mitodbYs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=hAFYOUhe; arc=none smtp.client-ip=209.85.222.175 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="hAFYOUhe" Received: by mail-qk1-f175.google.com with SMTP id af79cd13be357-7882e94d408so4659985a.0 for ; Wed, 13 Mar 2024 10:13:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1710350017; x=1710954817; 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=I2pOd3LND5n34HOza4BfVKn2HqMkXWPIWVe5Ll/LzXg=; b=hAFYOUhemx9ZSrH/Y9JqqZ2AMAPbFF3s4hb6c9ONX10IhY993c/D6p6vF6WpG1Bc9e FOVEDXaMYe/Vruxjx7ZVjIEDggFxMsdDf7tmURr70PgdNufPZts+F9x0+03EgwQGFO3u 2pzUp+1WzGSmeep1BZCqHiAfkvJ0aNfWnZoCFtbnZxzpSV8G6TbAuBU8jjiiPg6H8qyV YO1QsCtpGmXb4wICFVbvwyqzCbpWMd/+nNFEoPdYeGGhnoDnPR5MjK5dm22VLzuR9fKO M7e36feuqksAadD8D9418eSTds2dCqfkhwyvBaxksrnR5BNSZlSlCjRICWyfnAk+qxIC eIuQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1710350017; x=1710954817; 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=I2pOd3LND5n34HOza4BfVKn2HqMkXWPIWVe5Ll/LzXg=; b=sY+lmZXtvl+1NSUhkIRuveSV/qFQjdaAsy3wTAdZKr4B5i9yH+TG7xEg8tF5uaQ114 6U5HkXKJnmvtUWZPV7g29kmdmv1z7qDOojutesejEUJxEdS9ckZSRbpSAi0OE2NF3eTK r7rCAUuIboX3iHbOnzBlYOIs/QXNpeLRMaLU/djtoCtuIO9MqDEHe/Lti5V8tTH5xsOy A3f4By7VQZaYePNgdslfTe7mS9qR5boMQ/ImuSVc9dlIBrF5iEu75kHDRqFL6KqbV5SN 8/adshzhrxqzIlIgWiD8FB93nq9zDkgy83zBuFbTmE4cy6D3+Dd5YWGSIRrxZpq6HGfg 80iQ== X-Gm-Message-State: AOJu0Yy3KZCJ9hkcvJRw1urkN6G9+RBDq5IiqF6hVkUksAwUNa9FD8fW 3JIQshqtNE1nG45yXsWItV2CJI8bYdqf7nUs302kdnYliUeaxLAO00GoqrMs X-Google-Smtp-Source: AGHT+IH0oMPib90FrxTMSn6Y4BRw3SFIKqswpzmKIzR+UDyt89S86DuIUEoIfkTrtqZDTlmur4kd/w== X-Received: by 2002:a05:620a:211c:b0:788:776a:bcfa with SMTP id l28-20020a05620a211c00b00788776abcfamr451928qkl.74.1710350017371; Wed, 13 Mar 2024 10:13:37 -0700 (PDT) Received: from LOCLAP699.rst-01.locus ([208.195.13.130]) by smtp.gmail.com with ESMTPSA id i4-20020ae9ee04000000b007882e204d45sm4927136qkg.37.2024.03.13.10.13.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 13 Mar 2024 10:13:37 -0700 (PDT) From: James Prestwood To: iwd@lists.linux.dev Cc: James Prestwood Subject: [RFC 2/5] dpp-util: move AAD logic within dpp_append_wrapped_attributes Date: Wed, 13 Mar 2024 10:13:08 -0700 Message-Id: <20240313171311.695830-3-prestwoj@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240313171311.695830-1-prestwoj@gmail.com> References: <20240313171311.695830-1-prestwoj@gmail.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Leaving it up to the caller to calcluate the AAD resulted in lots of magic values, and any comments associated are spread out within dpp.c. The AAD values can be calculated entirely by the frame contents so move that within dpp_append_wrapped_data. The caller now only needs to pass the frame (after the mpdu header), the length, and the offset to where the wrapped data should start. The new AAD calculation includes all relavent comments so magic offsets are documented. The reason the entire mmpdu_body is not passed to dpp_append_wrapped_attributes (and one byte further) is to future proof for DPP encapsulation using TCP. For this, the category byte is omitted and only the action byte and further is encapsulated. Having dpp_append_wrapped_attributes start at the action byte allows it to work regardless of 8021x or TCP encapsulation. --- src/dpp-util.c | 167 +++++++++++++++++++++++++++++++++++++++++++++---- src/dpp-util.h | 5 +- src/dpp.c | 99 +++++++++++++++++------------ 3 files changed, 218 insertions(+), 53 deletions(-) diff --git a/src/dpp-util.c b/src/dpp-util.c index cfdedbdd..ada7ed96 100644 --- a/src/dpp-util.c +++ b/src/dpp-util.c @@ -39,6 +39,11 @@ #include "ell/asn1-private.h" #include "src/ie.h" +#define DPP_ACTION_VENDOR_SPECIFIC 0x09 +#define DPP_ACTION_GAS_REQUEST 0x0a +#define DPP_ACTION_GAS_RESPONSE 0x0b +#define DPP_HDR_LEN 6 + /* WFA Easy Connect v3.0 C.1 Role-specific Elements for NIST p256 */ static const uint8_t dpp_pkex_initiator_p256[64] = { /* X */ @@ -463,22 +468,91 @@ uint8_t *dpp_unwrap_attr(const void *ad0, size_t ad0_len, const void *ad1, return unwrapped; } +static bool dpp_aad(const uint8_t *frame, size_t frame_len, uint8_t *to, + const uint8_t **ad0, size_t *ad0_len, + const uint8_t **ad1, size_t *ad1_len) +{ + /* For PKEX frames */ + static uint8_t zero = 0; + static uint8_t one = 1; + enum dpp_frame_type type; + /* OUI field (inclusive) */ + const uint8_t *start = frame + 1; + + if (frame_len < 6) + return false; + + type = l_get_u8(frame + 6); + + switch (type) { + + case DPP_FRAME_AUTHENTICATION_REQUEST: + case DPP_FRAME_AUTHENTICATION_RESPONSE: + case DPP_FRAME_AUTHENTICATION_CONFIRM: + case DPP_FRAME_CONFIGURATION_RESULT: + /* + * Section 6.3.1.4 Protocol Conventions + * All other invocations of AES-SIV in the DPP Authentication + * protocol shall pass a vector of AAD having two components of + * AAD in the following order: + * (1) the DPP header, as defined in Table 34, from the OUI + * field (inclusive) to the DPP Frame Type field + * (inclusive); and + * (2) all octets in a DPP Public Action frame after the DPP + * Frame Type field up to and including the last octet + * of the last attribute before the Wrapped Data + * attribute + * + * Note: The configuration result frame uses identical wordage + * but is in Section 6.4.1 + */ + *ad0 = start; + *ad0_len = DPP_HDR_LEN; + *ad1 = start + DPP_HDR_LEN; + *ad1_len = to - start - DPP_HDR_LEN; + return true; + case DPP_FRAME_PKEX_COMMIT_REVEAL_REQUEST: + /* + * The AAD for this operation shall consist of two components: + * (1) the DPP header, as defined in Table 34, from the OUI + * field (inclusive) to the DPP Frame Type field + * (inclusive); and + * (2) a single octet of the value zero + */ + *ad0 = start; + *ad0_len = DPP_HDR_LEN; + *ad1 = &zero; + *ad1_len = 1; + return true; + case DPP_FRAME_PKEX_COMMIT_REVEAL_RESPONSE: + /* + * The AAD for this operation shall consist of two components: + * (1) the DPP header, as defined in Table 34, from the OUI + * field (inclusive) to the DPP Frame Type field + * (inclusive); and + * (2) a single octet of the value one + */ + *ad0 = start; + *ad0_len = DPP_HDR_LEN; + *ad1 = &one; + *ad1_len = 1; + return true; + default: + return false; + } +} + /* - * Encrypt DPP attributes encapsulated in DPP wrapped data. - * - * ad0/ad0_len - frame specific AD0 component - * ad1/ad0_len - frame specific AD1 component - * to - buffer to encrypt data. - * to_len - size of 'to' + * frame - start of action frame (excluding mpdu header and category) + * frame_len - total frame buffer size + * to - current position of DPP attributes (where wrapped data will start) * key - key used to encrypt * key_len - size of 'key' * num_attrs - number of attributes listed (type, length, data triplets) * ... - List of attributes, Type, Length, and data */ -size_t dpp_append_wrapped_data(const void *ad0, size_t ad0_len, - const void *ad1, size_t ad1_len, - uint8_t *to, size_t to_len, - const void *key, size_t key_len, +size_t dpp_append_wrapped_data(const uint8_t *frame, size_t frame_len, + uint8_t *to, const void *key, size_t key_len, size_t num_attrs, ...) { size_t i; @@ -488,6 +562,77 @@ size_t dpp_append_wrapped_data(const void *ad0, size_t ad0_len, struct iovec ad[2]; size_t ad_size = 0; va_list va; + uint8_t action; + const uint8_t *ad0 = NULL; + const uint8_t *ad1 = NULL; + size_t ad0_len, ad1_len; + + /* + * First determine the frame type. This could be passed in but due to + * The config protocol using GAS request/response frames not all frames + * map to a dpp_frame_type enum. Due to this, minimal parsing is done + * on the frame to determine the type, and in turn the AAD + * offsets/lengths. + */ + if (frame_len < 1) + return 0; + + action = *frame; + + switch (action) { + case DPP_ACTION_VENDOR_SPECIFIC: + if (!dpp_aad(frame, frame_len, to, &ad0, &ad0_len, + &ad1, &ad1_len)) + return 0; + + break; + /* + * Section 6.4.1 Overview + * + * "AAD for use with AES-SIV for protected messages in the DPP + * Configuration protocol shall consist of all octets in the + * Query Request and Query Response fields up to the first octet + * of the Wrapped Data attribute, which is the last attribute in a DPP + * Configuration frame. When the number of octets of AAD is zero, the + * number of components of AAD passed to AES-SIV is zero + */ + case DPP_ACTION_GAS_REQUEST: + /* + * 8.3.2 DPP Configuration Request frame + * The attributes begin 14 bytes after the action (inclusive) + */ + if (frame_len < 14) + return 0; + + /* Start of query request */ + ad0 = frame + 14; + /* "up to the first octet of the Wrapped Data attribute" */ + ad0_len = to - frame - 14; + + if (!ad0_len) + ad0 = NULL; + + break; + case DPP_ACTION_GAS_RESPONSE: + /* + * 8.3.3 DPP Configuration Response frame + * The attributes begin 18 bytes after the action (inclusive) + */ + if (frame_len < 18) + return 0; + + /* Start of query response */ + ad0 = frame + 18; + /* "up to the first octet of the Wrapped Data attribute" */ + ad0_len = to - frame - 18; + + if (!ad0_len) + ad0 = NULL; + + break; + default: + return 0; + } va_start(va, num_attrs); @@ -500,7 +645,7 @@ size_t dpp_append_wrapped_data(const void *ad0, size_t ad0_len, va_end(va); - if (to_len < attrs_len + 4 + 16) + if (frame_len - (to - frame) < attrs_len + 4 + 16) return false; plaintext = l_malloc(attrs_len); diff --git a/src/dpp-util.h b/src/dpp-util.h index dc8a894b..387750aa 100644 --- a/src/dpp-util.h +++ b/src/dpp-util.h @@ -148,9 +148,8 @@ uint8_t *dpp_unwrap_attr(const void *ad0, size_t ad0_len, const void *ad1, size_t *unwrapped_len); size_t dpp_append_attr(uint8_t *to, enum dpp_attribute_type type, void *attr, size_t attr_len); -size_t dpp_append_wrapped_data(const void *ad0, size_t ad0_len, const void *ad1, - size_t ad1_len, uint8_t *to, size_t to_len, - const void *key, size_t key_len, +size_t dpp_append_wrapped_data(const uint8_t *frame, size_t frame_len, + uint8_t *to, const void *key, size_t key_len, size_t num_attrs, ...); char *dpp_generate_uri(const uint8_t *asn1, size_t asn1_len, uint8_t version, diff --git a/src/dpp.c b/src/dpp.c index 5aac22a7..d710aa98 100644 --- a/src/dpp.c +++ b/src/dpp.c @@ -758,6 +758,9 @@ static void dpp_configuration_start(struct dpp_sm *dpp, const uint8_t *addr) size_t json_len = strlen(json); uint8_t *ptr = frame; uint8_t *lptr; + struct mmpdu_header *hdr = (struct mmpdu_header *)frame; + + memset(frame, 0, sizeof(frame)); l_getrandom(&dpp->diag_token, 1); @@ -779,7 +782,8 @@ static void dpp_configuration_start(struct dpp_sm *dpp, const uint8_t *addr) * In this case there is no query request/response fields, nor any * attributes besides wrapped data meaning zero AD components. */ - ptr += dpp_append_wrapped_data(NULL, 0, NULL, 0, ptr, sizeof(frame), + ptr += dpp_append_wrapped_data(mmpdu_body(hdr) + 1, + sizeof(frame) - mmpdu_header_len(hdr) - 1, ptr, dpp->ke, dpp->key_len, 2, DPP_ATTR_ENROLLEE_NONCE, dpp->nonce_len, dpp->e_nonce, DPP_ATTR_CONFIGURATION_REQUEST, json_len, json); @@ -800,11 +804,15 @@ static void send_config_result(struct dpp_sm *dpp, const uint8_t *to) uint8_t frame[256]; uint8_t *ptr = frame; uint8_t zero = 0; + struct mmpdu_header *hdr = (struct mmpdu_header *)frame; + + memset(frame, 0, sizeof(frame)); ptr += dpp_build_header(netdev_get_address(dpp->netdev), to, DPP_FRAME_CONFIGURATION_RESULT, ptr); - ptr += dpp_append_wrapped_data(frame + 26, 6, ptr, 0, ptr, - sizeof(frame), dpp->ke, dpp->key_len, 2, + ptr += dpp_append_wrapped_data(mmpdu_body(hdr) + 1, + sizeof(frame) - mmpdu_header_len(hdr) - 1, ptr, + dpp->ke, dpp->key_len, 2, DPP_ATTR_STATUS, (size_t) 1, &zero, DPP_ATTR_ENROLLEE_NONCE, dpp->nonce_len, dpp->e_nonce); @@ -1163,6 +1171,7 @@ static void dpp_send_config_response(struct dpp_sm *dpp, uint8_t status) size_t json_len; uint8_t *ptr = frame; uint8_t *lptr; + struct mmpdu_header *hdr = (struct mmpdu_header *)frame; memset(frame, 0, sizeof(frame)); @@ -1205,19 +1214,19 @@ static void dpp_send_config_response(struct dpp_sm *dpp, uint8_t status) json = dpp_configuration_to_json(dpp->config); json_len = strlen(json); - ptr += dpp_append_wrapped_data(lptr + 2, ptr - lptr - 2, - NULL, 0, ptr, sizeof(frame), - dpp->ke, dpp->key_len, 2, - DPP_ATTR_ENROLLEE_NONCE, - dpp->nonce_len, dpp->e_nonce, - DPP_ATTR_CONFIGURATION_OBJECT, - json_len, json); + ptr += dpp_append_wrapped_data(mmpdu_body(hdr) + 1, + sizeof(frame) - mmpdu_header_len(hdr) - 1, + ptr, dpp->ke, dpp->key_len, 2, + DPP_ATTR_ENROLLEE_NONCE, + dpp->nonce_len, dpp->e_nonce, + DPP_ATTR_CONFIGURATION_OBJECT, + json_len, json); } else - ptr += dpp_append_wrapped_data(lptr + 2, ptr - lptr - 2, - NULL, 0, ptr, sizeof(frame), - dpp->ke, dpp->key_len, 2, - DPP_ATTR_ENROLLEE_NONCE, - dpp->nonce_len, dpp->e_nonce); + ptr += dpp_append_wrapped_data(mmpdu_body(hdr) + 1, + sizeof(frame) - mmpdu_header_len(hdr) - 1, + ptr, dpp->ke, dpp->key_len, 2, + DPP_ATTR_ENROLLEE_NONCE, + dpp->nonce_len, dpp->e_nonce); l_put_le16(ptr - lptr - 2, lptr); @@ -1494,7 +1503,6 @@ static void send_authenticate_response(struct dpp_sm *dpp) { uint8_t frame[512]; uint8_t *ptr = frame; - uint8_t *attrs; uint8_t status = DPP_STATUS_OK; uint64_t r_proto_key[L_ECC_MAX_DIGITS * 2]; uint8_t version = 2; @@ -1502,6 +1510,9 @@ static void send_authenticate_response(struct dpp_sm *dpp) uint8_t wrapped2_plaintext[dpp->key_len + 4]; uint8_t wrapped2[dpp->key_len + 16 + 8]; size_t wrapped2_len; + struct mmpdu_header *hdr = (struct mmpdu_header *)frame; + + memset(frame, 0, sizeof(frame)); l_ecc_point_get_data(dpp->own_proto_public, r_proto_key, sizeof(r_proto_key)); @@ -1509,7 +1520,6 @@ static void send_authenticate_response(struct dpp_sm *dpp) ptr += dpp_build_header(netdev_get_address(dpp->netdev), dpp->peer_addr, DPP_FRAME_AUTHENTICATION_RESPONSE, ptr); - attrs = ptr; 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); @@ -1538,8 +1548,9 @@ static void send_authenticate_response(struct dpp_sm *dpp) wrapped2_len += 16; - ptr += dpp_append_wrapped_data(frame + 26, 6, attrs, ptr - attrs, - ptr, sizeof(frame), dpp->k2, dpp->key_len, 4, + ptr += dpp_append_wrapped_data(mmpdu_body(hdr) + 1, + sizeof(frame) - mmpdu_header_len(hdr) - 1, ptr, + dpp->k2, dpp->key_len, 4, DPP_ATTR_RESPONDER_NONCE, dpp->nonce_len, dpp->r_nonce, DPP_ATTR_INITIATOR_NONCE, dpp->nonce_len, dpp->i_nonce, DPP_ATTR_RESPONDER_CAPABILITIES, (size_t) 1, &dpp->role, @@ -1694,23 +1705,25 @@ static void dpp_auth_request_failed(struct dpp_sm *dpp, { uint8_t frame[128]; uint8_t *ptr = frame; - uint8_t *attrs; uint8_t version = 2; uint8_t s = status; struct iovec iov; + struct mmpdu_header *hdr = (struct mmpdu_header *)frame; + + memset(frame, 0, sizeof(frame)); ptr += dpp_build_header(netdev_get_address(dpp->netdev), dpp->peer_addr, DPP_FRAME_AUTHENTICATION_RESPONSE, ptr); - attrs = ptr; ptr += dpp_append_attr(ptr, DPP_ATTR_STATUS, &s, 1); ptr += dpp_append_attr(ptr, DPP_ATTR_RESPONDER_BOOT_KEY_HASH, dpp->own_boot_hash, 32); ptr += dpp_append_attr(ptr, DPP_ATTR_PROTOCOL_VERSION, &version, 1); - ptr += dpp_append_wrapped_data(frame + 26, 6, attrs, ptr - attrs, - ptr, sizeof(frame) - (ptr - attrs), k1, dpp->key_len, 2, + ptr += dpp_append_wrapped_data(mmpdu_body(hdr) + 1, + sizeof(frame) - mmpdu_header_len(hdr) - 1, ptr, + k1, dpp->key_len, 2, DPP_ATTR_INITIATOR_NONCE, dpp->nonce_len, dpp->i_nonce, DPP_ATTR_RESPONDER_CAPABILITIES, (size_t) 1, &dpp->role); @@ -1765,12 +1778,14 @@ static bool dpp_send_authenticate_request(struct dpp_sm *dpp) { uint8_t frame[256]; uint8_t *ptr = frame; - uint8_t *attrs; uint64_t i_proto_key[L_ECC_MAX_DIGITS * 2]; uint8_t version = 2; struct iovec iov; struct station *station = station_find(netdev_get_ifindex(dpp->netdev)); struct scan_bss *bss = station_get_connected_bss(station); + struct mmpdu_header *hdr = (struct mmpdu_header *)frame; + + memset(frame, 0, sizeof(frame)); /* Got disconnected by the time the peer was discovered */ if (dpp->role == DPP_CAPABILITY_CONFIGURATOR && !bss) { @@ -1784,8 +1799,6 @@ static bool dpp_send_authenticate_request(struct dpp_sm *dpp) ptr += dpp_build_header(netdev_get_address(dpp->netdev), dpp->peer_addr, DPP_FRAME_AUTHENTICATION_REQUEST, ptr); - attrs = ptr; - ptr += dpp_append_attr(ptr, DPP_ATTR_RESPONDER_BOOT_KEY_HASH, dpp->peer_boot_hash, 32); ptr += dpp_append_attr(ptr, DPP_ATTR_INITIATOR_BOOT_KEY_HASH, @@ -1802,8 +1815,9 @@ static bool dpp_send_authenticate_request(struct dpp_sm *dpp) ptr += dpp_append_attr(ptr, DPP_ATTR_CHANNEL, pair, 2); } - ptr += dpp_append_wrapped_data(frame + 26, 6, attrs, ptr - attrs, - ptr, sizeof(frame), dpp->k1, dpp->key_len, 2, + ptr += dpp_append_wrapped_data(mmpdu_body(hdr) + 1, + sizeof(frame) - mmpdu_header_len(hdr) - 1, ptr, + dpp->k1, dpp->key_len, 2, DPP_ATTR_INITIATOR_NONCE, dpp->nonce_len, dpp->i_nonce, DPP_ATTR_INITIATOR_CAPABILITIES, (size_t) 1, &dpp->role); @@ -1857,9 +1871,11 @@ static void dpp_send_commit_reveal_request(struct dpp_sm *dpp) struct iovec iov; uint8_t frame[512]; uint8_t *ptr = frame; - uint8_t zero = 0; uint8_t a_pub[L_ECC_POINT_MAX_BYTES]; ssize_t a_len; + struct mmpdu_header *hdr = (struct mmpdu_header *)frame; + + memset(frame, 0, sizeof(frame)); a_len = l_ecc_point_get_data(dpp->boot_public, a_pub, sizeof(a_pub)); @@ -1867,8 +1883,9 @@ static void dpp_send_commit_reveal_request(struct dpp_sm *dpp) dpp->peer_addr, DPP_FRAME_PKEX_COMMIT_REVEAL_REQUEST, ptr); - ptr += dpp_append_wrapped_data(frame + 26, 6, &zero, 1, ptr, - sizeof(frame), dpp->z, dpp->z_len, 2, + ptr += dpp_append_wrapped_data(mmpdu_body(hdr) + 1, + sizeof(frame) - mmpdu_header_len(hdr) - 1, ptr, + dpp->z, dpp->z_len, 2, DPP_ATTR_BOOTSTRAPPING_KEY, a_len, a_pub, DPP_ATTR_INITIATOR_AUTH_TAG, dpp->u_len, dpp->u); @@ -2264,13 +2281,14 @@ static void dpp_send_authenticate_confirm(struct dpp_sm *dpp) struct iovec iov; uint8_t frame[256]; uint8_t *ptr = frame; - uint8_t *attrs; uint8_t zero = 0; + struct mmpdu_header *hdr = (struct mmpdu_header *)frame; + + memset(frame, 0, sizeof(frame)); ptr += dpp_build_header(netdev_get_address(dpp->netdev), dpp->peer_addr, DPP_FRAME_AUTHENTICATION_CONFIRM, ptr); - attrs = ptr; 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); @@ -2278,8 +2296,9 @@ static void dpp_send_authenticate_confirm(struct dpp_sm *dpp) ptr += dpp_append_attr(ptr, DPP_ATTR_INITIATOR_BOOT_KEY_HASH, dpp->own_boot_hash, 32); - ptr += dpp_append_wrapped_data(frame + 26, 6, attrs, ptr - attrs, ptr, - sizeof(frame), dpp->ke, dpp->key_len, 1, + ptr += dpp_append_wrapped_data(mmpdu_body(hdr) + 1, + sizeof(frame) - mmpdu_header_len(hdr) - 1, ptr, + dpp->ke, dpp->key_len, 1, DPP_ATTR_INITIATOR_AUTH_TAG, dpp->key_len, dpp->auth_tag); @@ -3301,19 +3320,21 @@ static void dpp_send_commit_reveal_response(struct dpp_sm *dpp, { uint8_t frame[256]; uint8_t *ptr = frame; - uint8_t one = 1; struct iovec iov; const uint8_t *own_mac = netdev_get_address(dpp->netdev); uint8_t b_pub[L_ECC_POINT_MAX_BYTES]; size_t b_len; + struct mmpdu_header *hdr = (struct mmpdu_header *)frame; - b_len = l_ecc_point_get_data(dpp->boot_public, b_pub, sizeof(b_pub)); + memset(frame, 0, sizeof(frame)); + b_len = l_ecc_point_get_data(dpp->boot_public, b_pub, sizeof(b_pub)); ptr += dpp_build_header(own_mac, dpp->peer_addr, DPP_FRAME_PKEX_COMMIT_REVEAL_RESPONSE, ptr); - ptr += dpp_append_wrapped_data(frame + 26, 6, &one, 1, ptr, - sizeof(frame), dpp->z, dpp->z_len, 2, + ptr += dpp_append_wrapped_data(mmpdu_body(hdr) + 1, + sizeof(frame) - mmpdu_header_len(hdr) - 1, ptr, + dpp->z, dpp->z_len, 2, DPP_ATTR_BOOTSTRAPPING_KEY, b_len, b_pub, DPP_ATTR_RESPONDER_AUTH_TAG, v_len, v); From patchwork Wed Mar 13 17:13:09 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Prestwood X-Patchwork-Id: 13591632 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 DEC497BAE7 for ; Wed, 13 Mar 2024 17:13:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.180 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1710350021; cv=none; b=Jkz9H8KSXLl1NokLhq7MvxpCCdla9xhQz9NeNkM/yZCAg+2Dp+kThjep6wRRbd+zVXixy46LVOudskmjyRJl/Z9dbus5H5u2S3DQVPI4b/PcY41sbWkyLinkVTJkIbdilpRezcXw3cIp77lwxYJXNzGtsXv46wUxxHqJgUqp6XM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1710350021; c=relaxed/simple; bh=lb9/VaPQdNylr3CnZS/warLCHD/03kqFpnOXWC0cQeg=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=TcXjpxTK/Jf8dJWM2zhKCAr6cbtdRIw5jFb6dDADn4v0zXOwA0JfO0LBA2V9a7PUgBRUshYxDdo3FFshEshiDz96E1imRttsepmuGOBvA68wQITd5YBDE9t3pFB5dn5ZC7+f4YJt6ZukOEuZXSPlEz7MXsOXJYpn2xVh65I4kss= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=e8JAEYcc; arc=none smtp.client-ip=209.85.222.180 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="e8JAEYcc" Received: by mail-qk1-f180.google.com with SMTP id af79cd13be357-7882b1e87c4so3046685a.1 for ; Wed, 13 Mar 2024 10:13:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1710350018; x=1710954818; 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=TfggQUFqh8R0OL7pLM6apbCSjclCuBMPEFy6joovcww=; b=e8JAEYccbZpzAv9y7XnaaPJjzEGVPyuX4DJB2+/qFyP8yG2yHuGGjWcoWCgUhUO4ZE N4ldHdayFpx87ssUVdhNrdyQPCX12kt06BhovG0MXlU4ff1544BbW2SP0fYyO2ptg9ft EEZoygJmiEJcMutsOuruY4qWooF5b3uAOJ0yUP3g09vIJDraWEXy8shd8mWtBD1a6zKp rE+lgk2PPzwmVvL+Pr66nx0wLqwEufUV/JQZ4f7upH4P4a7BQj7iusZRvy3mc79oXsw2 AIXbUpffitlDSJWmw4WVB5s4wdGuDE8BsOkdcI2xvzhhC7BzRZitIi6hsNwKjTNzJcKU v45w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1710350018; x=1710954818; 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=TfggQUFqh8R0OL7pLM6apbCSjclCuBMPEFy6joovcww=; b=UcUMz+L8GcQ9y0HcTR0tLnLqQ9DSdZh3SrNEOo3uh7X7waxrSSrBrwxdkBK6fOsYJP 49Wbtf2GsAedTJbv2S79M663+rEJWLd8LcUwpCdlPWG6yDajh+1xM4VzpTO7V3kAMPJR lZBRGC/JOpMhIbdVH6N0xzZrJaFzo8szDtHSvxtaz9sA5ltxG9pgN3xpttkHtLwniSZo 1e299nIOfGa/oY0Nifby7CnhFa+DF9jdE9NZtvLz7HgUBW4aq7XAB7xa/wAg/ev3TOUw 4b6ETR9gv4ZbEg4lgmYkQpXwxbPOIWZlYw+fZNwriZKgYxsh0D3dtBpL9sT6Lt8fkYVJ 8TfQ== X-Gm-Message-State: AOJu0YxIdVBqWqaw9St+J5tx0tbBBOf4HgqEIabirI4i8EyzwPSkVSos Iw994o3Lh2qROz5ZEvrw7ke4FHwnAmekRF9RTGycuovkE9yom6h80JD3h3BI X-Google-Smtp-Source: AGHT+IEQHVwOpFn4q0x9jThNAr1rtY/5qB3I8lJ+vdS772nllnc+EBQ5U6HGHTE9ZjTOFKns/4wGyw== X-Received: by 2002:a05:620a:1363:b0:788:2190:d293 with SMTP id d3-20020a05620a136300b007882190d293mr468027qkl.40.1710350018475; Wed, 13 Mar 2024 10:13:38 -0700 (PDT) Received: from LOCLAP699.rst-01.locus ([208.195.13.130]) by smtp.gmail.com with ESMTPSA id i4-20020ae9ee04000000b007882e204d45sm4927136qkg.37.2024.03.13.10.13.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 13 Mar 2024 10:13:38 -0700 (PDT) From: James Prestwood To: iwd@lists.linux.dev Cc: James Prestwood Subject: [RFC 3/5] dpp-util: add dpp_append_point Date: Wed, 13 Mar 2024 10:13:09 -0700 Message-Id: <20240313171311.695830-4-prestwoj@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240313171311.695830-1-prestwoj@gmail.com> References: <20240313171311.695830-1-prestwoj@gmail.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Any time DPP needs to append a point it has to use a temporary buffer to copy into, then copy that into the message buffer. Instead of this add a special purpose API to add the type/length then copy the data directly into the message buffer. --- src/dpp-util.c | 13 +++++++++++++ src/dpp-util.h | 2 ++ 2 files changed, 15 insertions(+) diff --git a/src/dpp-util.c b/src/dpp-util.c index ada7ed96..81f34047 100644 --- a/src/dpp-util.c +++ b/src/dpp-util.c @@ -697,6 +697,19 @@ size_t dpp_append_wrapped_data(const uint8_t *frame, size_t frame_len, return attrs_len + 4 + 16; } +size_t dpp_append_point(uint8_t *to, enum dpp_attribute_type type, + struct l_ecc_point *point) +{ + const struct l_ecc_curve *c = l_ecc_point_get_curve(point); + size_t len = l_ecc_curve_get_scalar_bytes(c) * 2; + + l_put_le16(type, to); + l_put_le16(len, to + 2); + l_ecc_point_get_data(point, to + 4, len); + + return len + 4; +} + /* * EasyConnect 2.0 Table 3. Key and Nonce Length Dependency on Prime Length */ diff --git a/src/dpp-util.h b/src/dpp-util.h index 387750aa..1ff9004d 100644 --- a/src/dpp-util.h +++ b/src/dpp-util.h @@ -151,6 +151,8 @@ size_t dpp_append_attr(uint8_t *to, enum dpp_attribute_type type, size_t dpp_append_wrapped_data(const uint8_t *frame, size_t frame_len, uint8_t *to, const void *key, size_t key_len, size_t num_attrs, ...); +size_t dpp_append_point(uint8_t *to, enum dpp_attribute_type type, + struct l_ecc_point *point); char *dpp_generate_uri(const uint8_t *asn1, size_t asn1_len, uint8_t version, const uint8_t *mac, const uint32_t *freqs, From patchwork Wed Mar 13 17:13:10 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Prestwood X-Patchwork-Id: 13591633 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 20E077BB01 for ; Wed, 13 Mar 2024 17:13:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.175 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1710350023; cv=none; b=giN3E1OQTRYC6TiriudfrN1kYL7gEuuqkzSWTfhl1Gtz9NozRA0SMEkiTnMiVIEtvSccijDJBbBdQhDZOwH2ZDKSTns3nCxhqG/ylDTA2S+5Jzv/ShWtG1l7BXEYBLCNvrrRxoAFSHErqp7sOaOAZkbnviUGMM0EpxMrS1Wglmg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1710350023; c=relaxed/simple; bh=SkVB6yaCtiY19HRA+P1Ou0mgmy5p+loI4m5zMOeA9OE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=aN2vy8SUQ3sSavsoMYThX/hQQoxZ0XX5Pb4+O0uFqIFISZQh9YpzUwVi/oNPil81zrtLwWcvH7ny8fimfjsWAcYvw4G0bAjWAkZ4asHW359uYw7yoxk4lmKr+BO1FlWbDPX2nGuiLb1b9sV5fZZ5boFe+Hb2AJHPWzaXYOJXnZc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=hImwDSIJ; arc=none smtp.client-ip=209.85.222.175 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="hImwDSIJ" Received: by mail-qk1-f175.google.com with SMTP id af79cd13be357-7884a9a404fso3330985a.3 for ; Wed, 13 Mar 2024 10:13:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1710350019; x=1710954819; 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=2I6EtzXK2xSu8dxZO7eznX3LUgn7LoxAObVVvvJZ4uM=; b=hImwDSIJ/NgA6WZ/yq6afJjTb5vddG6PTpAn7IvlXzzfsQphjR/E/nBllbWMRu7Pcn PGiEKI58/2Y0yTH8p7nf3ePzh+wsQqsiZY5CuZiAoQKE6Vp0novKMuF5gUpOxxVHYWGa Obxo8dQopOxbGKWo3i9F47frEWW7+O/H4oSb3H4CojMT76ca8NjYqDMItrdipUcPd8OI d9RyH4kjnQzlvq9ngjwwE1lwF05EkZQyzrJkdBBk907z+74W8NnGIJazZfippiGWrFpE /k+wCDtTTETgJ03tEOgJega4nHocNEcpC6OzK3k8izJVIJH+5BzvllD0y0h44kEVEFSi Wq7w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1710350019; x=1710954819; 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=2I6EtzXK2xSu8dxZO7eznX3LUgn7LoxAObVVvvJZ4uM=; b=A+JqNv/RKecUhU6UBdYD7IApc8evdkv7eIDAjKPYJmKBQnQfyaM+0BsyD8v2aSrpqO xmnzQjQNB41V3GYU5bcpFnxuoxYin/hdURS04sqlyjgXEgAKnm+h/J0ExdSHKPz7QT6a vjd/w8XI4bNL2yjYHtT80eGXSOWuY79476ZWsfyL22ks8Bx6T9qnNIDQQB8Tjcv09khK 7X3sPSO2GOXt9AMJVBshuGBXptyyAJEApjFkaZCWHToEVJf/wg3PjYMmuYAE0J80pYDz iquek8HmGC80aSbPZbgytyegd3g9jot+6QKoOIAw/m/rOlB+lqdXvuUKAUWrZRPlktk+ vE9A== X-Gm-Message-State: AOJu0YzSHmKhXG9r+qu2+P4XW2LufX77ocA8yN3QFQ9yUtWvY82IFYrg dMQlky53k6SyFFNQUNpCdMeljnNPLKqrEN/SWGhhRP34pL0ynazfIf6Va0p9 X-Google-Smtp-Source: AGHT+IFSqti2AKulEQdcXsMEd6UdbXKPYEmHs6qlUovkbIlydm2KuRkT9YUCc4XTwu1zYCBHyfb6QA== X-Received: by 2002:a05:620a:ecc:b0:788:2b1c:1e57 with SMTP id x12-20020a05620a0ecc00b007882b1c1e57mr476280qkm.55.1710350019585; Wed, 13 Mar 2024 10:13:39 -0700 (PDT) Received: from LOCLAP699.rst-01.locus ([208.195.13.130]) by smtp.gmail.com with ESMTPSA id i4-20020ae9ee04000000b007882e204d45sm4927136qkg.37.2024.03.13.10.13.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 13 Mar 2024 10:13:39 -0700 (PDT) From: James Prestwood To: iwd@lists.linux.dev Cc: James Prestwood Subject: [RFC 4/5] dpp: use dpp_append_point Date: Wed, 13 Mar 2024 10:13:10 -0700 Message-Id: <20240313171311.695830-5-prestwoj@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240313171311.695830-1-prestwoj@gmail.com> References: <20240313171311.695830-1-prestwoj@gmail.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Use dpp_append_point where possible to avoid temporarily copying data --- src/dpp.c | 28 ++++++---------------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/src/dpp.c b/src/dpp.c index d710aa98..47ebd495 100644 --- a/src/dpp.c +++ b/src/dpp.c @@ -1504,7 +1504,6 @@ static void send_authenticate_response(struct dpp_sm *dpp) uint8_t frame[512]; uint8_t *ptr = frame; uint8_t status = DPP_STATUS_OK; - uint64_t r_proto_key[L_ECC_MAX_DIGITS * 2]; uint8_t version = 2; struct iovec iov; uint8_t wrapped2_plaintext[dpp->key_len + 4]; @@ -1514,9 +1513,6 @@ static void send_authenticate_response(struct dpp_sm *dpp) memset(frame, 0, sizeof(frame)); - l_ecc_point_get_data(dpp->own_proto_public, r_proto_key, - sizeof(r_proto_key)); - ptr += dpp_build_header(netdev_get_address(dpp->netdev), dpp->peer_addr, DPP_FRAME_AUTHENTICATION_RESPONSE, ptr); @@ -1526,8 +1522,8 @@ static void send_authenticate_response(struct dpp_sm *dpp) 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_point(ptr, DPP_ATTR_RESPONDER_PROTOCOL_KEY, + dpp->own_proto_public); ptr += dpp_append_attr(ptr, DPP_ATTR_PROTOCOL_VERSION, &version, 1); /* Wrap up secondary data (R-Auth) */ @@ -1778,7 +1774,6 @@ static bool dpp_send_authenticate_request(struct dpp_sm *dpp) { uint8_t frame[256]; uint8_t *ptr = frame; - uint64_t i_proto_key[L_ECC_MAX_DIGITS * 2]; uint8_t version = 2; struct iovec iov; struct station *station = station_find(netdev_get_ifindex(dpp->netdev)); @@ -1793,9 +1788,6 @@ static bool dpp_send_authenticate_request(struct dpp_sm *dpp) return false; } - l_ecc_point_get_data(dpp->own_proto_public, i_proto_key, - sizeof(i_proto_key)); - ptr += dpp_build_header(netdev_get_address(dpp->netdev), dpp->peer_addr, DPP_FRAME_AUTHENTICATION_REQUEST, ptr); @@ -1803,8 +1795,8 @@ static bool dpp_send_authenticate_request(struct dpp_sm *dpp) dpp->peer_boot_hash, 32); ptr += dpp_append_attr(ptr, DPP_ATTR_INITIATOR_BOOT_KEY_HASH, dpp->own_boot_hash, 32); - ptr += dpp_append_attr(ptr, DPP_ATTR_INITIATOR_PROTOCOL_KEY, - i_proto_key, dpp->key_len * 2); + ptr += dpp_append_point(ptr, DPP_ATTR_INITIATOR_PROTOCOL_KEY, + dpp->own_proto_public); ptr += dpp_append_attr(ptr, DPP_ATTR_PROTOCOL_VERSION, &version, 1); if (dpp->role == DPP_CAPABILITY_CONFIGURATOR && @@ -1835,7 +1827,6 @@ 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); @@ -1855,10 +1846,7 @@ static void dpp_send_pkex_exchange_request(struct dpp_sm *dpp) 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); + ptr += dpp_append_point(ptr, DPP_ATTR_ENCRYPTED_KEY, dpp->pkex_m); iov[1].iov_base = attrs; iov[1].iov_len = ptr - attrs; @@ -3018,7 +3006,6 @@ static void dpp_send_pkex_exchange_response(struct dpp_sm *dpp, 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]; @@ -3036,10 +3023,7 @@ static void dpp_send_pkex_exchange_response(struct dpp_sm *dpp, 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); + ptr += dpp_append_point(ptr, DPP_ATTR_ENCRYPTED_KEY, n); iov[1].iov_base = attrs; iov[1].iov_len = ptr - attrs; From patchwork Wed Mar 13 17:13:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Prestwood X-Patchwork-Id: 13591634 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 4D4EC6167D for ; Wed, 13 Mar 2024 17:13:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.170 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1710350024; cv=none; b=qtaEP8DdLhJ8sNVdk+DPJlqg5pe1Nr2ym7KUgz2MAPIm2npgAyNlgFOV0yAhzy94Z3Wkl1ZC1a58KznAxK1CzvXpMPjNPDLu0ogQ7eI38sw40elSMo9Ca5OQGJv+HS1TD1AZN1rQR326BLfZymBd4n/kV3P++N2wiqYV6hAsBT4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1710350024; c=relaxed/simple; bh=RyRQuBH1LxzpSV56XjuyxRfcocsO2kVbhhqeZ0VSBvU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=ErI6o5jGoK8DM3BaHqD5I9lusZcFQVD+kTcOG3XEgYEI4LHbtk9eVSUQbJ6pNXOdsXhkdbl/yJyhYFUixa3bO7DU1pP3oik3BZa0Da+JEBy4f05kzYYdZkQEcpvbT58x2ZG1HirpF9vEaYQebAPumPIErx0huJoI4HOnMSDVeY8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=kNpfCePK; arc=none smtp.client-ip=209.85.222.170 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="kNpfCePK" Received: by mail-qk1-f170.google.com with SMTP id af79cd13be357-7882dd2b1c9so9735185a.1 for ; Wed, 13 Mar 2024 10:13:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1710350021; x=1710954821; 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=0Hmvr3guvtsSvUSiUxFQItOc7jCBwPLc/JfCKLcCWcU=; b=kNpfCePK+HGb0Uc5Dixn/H916ZuhwtVtN1rA7G40sKKNqn3vYK3N5wjC7QnbHyfRrT O+Fa+v7Jl6bw/mb/iqQtkiYCEyVQ8P933IADRNjIgBCRMFNNgv0Oq+A9+p01Ga3IQCAg ivDl5WEiHLVdXxvrV2X298cO45lZyxAbAVGubxlJdKOpP1HceMv3fbErawRqczAjjKks Ptc26laYC8Nzly5uXpFHQmBLWp2kqfJJWdlwY5CApNWuW1DckNVF6Tksy/c5tyQaVnud WeZ1ProgPmsnxcrXfzJLqxh+Zn5feLOeOze5AAghmqYseEiOH5+gkl71+STcwFyCb6sW 6D/g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1710350021; x=1710954821; 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=0Hmvr3guvtsSvUSiUxFQItOc7jCBwPLc/JfCKLcCWcU=; b=nM9cDCip6PQkmIeXhzUdIYMF0BCpIajTzNpiWqRxIgmC+zdmuPraOM4bZXaacqj8xk z0C71LtvAl4UWFxJL3Z3g/VdKpKHjGszXdfoBHZNzVc1eXP0UL3JwEf6E/HlGFaJDd3I PVxxSLifJSSh3+QcShnPb2NH8DLMMYztQzQRVqoXkxCOKKdqxCNp41N+vEIeX5fWJho4 IVVW790BsL6WRFN7mLj4J1Xo/+1Z7bt0it/0BFVL8+msMcdJKkPgU3jgZ7ypdR+km7aJ wbvHwCXL5mz++fWXDLuyD+tFJHK6lyx7QsiQYv+i+wwqRizohtzS5uZwrRSS/GNWz/qt Z+PQ== X-Gm-Message-State: AOJu0Yxieqa0mF0l118r6/6aU6GboVREN8JTqKHy8TWsU+8JiWNP4Daz HZbQV7XssOYwO6IbWPoSNTKoJuwShqaC0Q2h2CXGsWbYWjVR0DPTV05GH4Hn X-Google-Smtp-Source: AGHT+IHmdCk+sO6T2qjvC7w6AuDzNyEATeExgfoA/x8a17uJTaqt73J/vE8P1y/H3EwUFlHAKLMdTA== X-Received: by 2002:a05:620a:17a5:b0:788:79d3:4029 with SMTP id ay37-20020a05620a17a500b0078879d34029mr716997qkb.33.1710350020666; Wed, 13 Mar 2024 10:13:40 -0700 (PDT) Received: from LOCLAP699.rst-01.locus ([208.195.13.130]) by smtp.gmail.com with ESMTPSA id i4-20020ae9ee04000000b007882e204d45sm4927136qkg.37.2024.03.13.10.13.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 13 Mar 2024 10:13:40 -0700 (PDT) From: James Prestwood To: iwd@lists.linux.dev Cc: James Prestwood Subject: [RFC 5/5] dpp-common: Skeleton for common DPP module Date: Wed, 13 Mar 2024 10:13:11 -0700 Message-Id: <20240313171311.695830-6-prestwoj@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240313171311.695830-1-prestwoj@gmail.com> References: <20240313171311.695830-1-prestwoj@gmail.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 In order to expand the features for DPP e.g. TCP or a DPP controller the state machine needs to be both transport agnostic and buildable for other apps outside of IWD-core. To do this the core DPP state machine is being moved into a common module. The consumers of the common SM will create a dpp_sm object for each protocol run, and destroy it afterwards. The SM will take a write callback, event callback, the boostrapping keys, and expose a read handler: - The write callback will be called by the SM whenever there is a frame to be sent out. In order to support 802.11 encapsulation dpp_sm_set_write_handler can be used to notify the SM that writes are allowed or disallowed (by passing NULL). This is done to allow the 802.11 encapsulating module to prepare any offchannel requests before sending out frames. - The event callback is called by the SM whenever there are events requiring some handling by the encapsulating protocol, or when DPP has succeeded or failed. - The read handler can be called by the encapsulating protocol in order to RX frames to the SM. Making the SM common will allow both pure-802.11 DPP and DPP-over-TCP to utilize the same state machine. In addition a DPP-controller can now be implemented using the common SM but be entirely standalone from IWD. --- src/dpp-common.c | 517 +++++++++++++++++++++++++++++++++++++++++++++++ src/dpp-common.h | 109 ++++++++++ 2 files changed, 626 insertions(+) create mode 100644 src/dpp-common.c create mode 100644 src/dpp-common.h diff --git a/src/dpp-common.c b/src/dpp-common.c new file mode 100644 index 00000000..af0645df --- /dev/null +++ b/src/dpp-common.c @@ -0,0 +1,517 @@ +/* + * + * Wireless daemon for Linux + * + * Copyright (C) 2024 Locus Robotics + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include + +#include "linux/nl80211.h" + +#include "src/missing.h" +#include "src/dbus.h" +#include "src/netdev.h" +#include "src/module.h" +#include "src/dpp-util.h" +#include "src/band.h" +#include "src/frame-xchg.h" +#include "src/offchannel.h" +#include "src/wiphy.h" +#include "src/ie.h" +#include "src/iwd.h" +#include "src/util.h" +#include "src/crypto.h" +#include "src/mpdu.h" +#include "ell/useful.h" +#include "src/common.h" +#include "src/json.h" +#include "src/storage.h" +#include "src/station.h" +#include "src/scan.h" +#include "src/network.h" +#include "src/handshake.h" +#include "src/nl80211util.h" +#include "src/knownnetworks.h" +#include "src/dpp-common.h" + +#define DPP_HDR_LEN 6 +#define DPP_ACTION_VENDOR_SPECIFIC 0x09 +#define DPP_ACTION_GAS_REQUEST 0x0a +#define DPP_ACTION_GAS_RESPONSE 0x0b +#define DPP_AUTH_PROTO_TIMEOUT 10 +#define DPP_PKEX_PROTO_TIMEOUT 120 + +struct dpp_sm { + char *uri; + uint8_t role; + + uint8_t *own_asn1; + size_t own_asn1_len; + uint8_t *peer_asn1; + size_t peer_asn1_len; + uint8_t own_boot_hash[32]; + uint8_t peer_boot_hash[32]; + uint8_t own_chirp_hash[32]; + const struct l_ecc_curve *curve; + size_t key_len; + size_t nonce_len; + struct l_ecc_scalar *boot_private; + struct l_ecc_point *boot_public; + struct l_ecc_point *peer_boot_public; + + enum dpp_state state; + + uint8_t r_nonce[32]; + uint8_t i_nonce[32]; + uint8_t e_nonce[32]; + + struct l_ecc_scalar *m; + uint64_t ke[L_ECC_MAX_DIGITS]; + uint64_t k1[L_ECC_MAX_DIGITS]; + uint64_t k2[L_ECC_MAX_DIGITS]; + uint64_t auth_tag[L_ECC_MAX_DIGITS]; + + struct l_ecc_scalar *proto_private; + struct l_ecc_point *own_proto_public; + + struct l_ecc_point *peer_proto_public; + + uint8_t diag_token; + + /* Timeout of auth/config/PKEX protocols */ + uint64_t proto_timeout; + struct l_timeout *timeout; + + struct dpp_configuration *config; + + /* PKEX-specific values */ + 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; + /* 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; + uint8_t pkex_own_mac[6]; + uint8_t pkex_peer_mac[6]; + /* Set to either own/peer mac depending on configuration */ + const uint8_t *mac_initiator; + const uint8_t *mac_responder; + + /* + * Since the authenticate frame may request a channel switch we do need + * to expose this detail within the common code. + */ + uint8_t channel[2]; + + uint8_t *frame_pending; + size_t frame_len; + dpp_write_cb_t write; + dpp_event_cb_t event_cb; + void *user_data; + + bool skip_presence : 1; + bool mutual_auth : 1; + bool initiator : 1; +}; + +static void dpp_failed(struct dpp_sm *dpp) +{ + if (dpp->event_cb) + dpp->event_cb(DPP_EVENT_FAILED, NULL, dpp->user_data); +} + +static void dpp_protocol_timeout(struct l_timeout *timeout, void *user_data) +{ + struct dpp_sm *dpp = user_data; + + l_debug("DPP timed out"); + + dpp_failed(dpp); +} + +static void dpp_reset_protocol_timer(struct dpp_sm *dpp, uint64_t time) +{ + if (dpp->timeout) + l_timeout_modify(dpp->timeout, time); + else + dpp->timeout = l_timeout_create(time, dpp_protocol_timeout, + dpp, NULL); +} + +struct dpp_sm *dpp_sm_new(dpp_event_cb_t event, + const struct l_ecc_point *boot_public, + const struct l_ecc_scalar *boot_private, + void *user_data) +{ + struct dpp_sm *dpp = l_new(struct dpp_sm, 1); + + dpp->state = DPP_STATE_NOTHING; + dpp->curve = l_ecc_point_get_curve(boot_public); + dpp->key_len = l_ecc_curve_get_scalar_bytes(dpp->curve); + dpp->nonce_len = dpp_nonce_len_from_key_len(dpp->key_len); + dpp->boot_public = l_ecc_point_clone(boot_public); + dpp->boot_private = l_ecc_scalar_clone(boot_private); + dpp->own_asn1 = dpp_point_to_asn1(dpp->boot_public, &dpp->own_asn1_len); + dpp->event_cb = event; + dpp->user_data = user_data; + + dpp_hash(L_CHECKSUM_SHA256, dpp->own_boot_hash, 1, dpp->own_asn1, + dpp->own_asn1_len); + dpp_hash(L_CHECKSUM_SHA256, dpp->own_chirp_hash, 2, "chirp", + strlen("chirp"), dpp->own_asn1, dpp->own_asn1_len); + + return dpp; +} + +void dpp_sm_set_write_handler(struct dpp_sm *dpp, dpp_write_cb_t write) +{ + dpp->write = write; + + if (!dpp->write) + return; + + /* Handle writing frame */ +} + +static void dpp_free_auth_data(struct dpp_sm *dpp) +{ + if (dpp->own_proto_public) { + l_ecc_point_free(dpp->own_proto_public); + dpp->own_proto_public = NULL; + } + + if (dpp->proto_private) { + l_ecc_scalar_free(dpp->proto_private); + dpp->proto_private = NULL; + } + + if (dpp->peer_proto_public) { + l_ecc_point_free(dpp->peer_proto_public); + dpp->peer_proto_public = NULL; + } + + if (dpp->peer_boot_public) { + l_ecc_point_free(dpp->peer_boot_public); + dpp->peer_boot_public = NULL; + } + + if (dpp->m) { + 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_free_pending_pkex_data(struct dpp_sm *dpp) +{ + if (dpp->pkex_id) { + l_free(dpp->pkex_id); + dpp->pkex_id = NULL; + } + + if (dpp->pkex_key) { + l_free(dpp->pkex_key); + dpp->pkex_key = NULL; + } + + if (dpp->peer_encr_key) { + l_ecc_point_free(dpp->peer_encr_key); + dpp->peer_encr_key = NULL; + } +} + +void dpp_sm_free(struct dpp_sm *dpp) +{ + if (dpp->boot_public) { + l_ecc_point_free(dpp->boot_public); + dpp->boot_public = NULL; + } + + if (dpp->boot_private) { + l_ecc_scalar_free(dpp->boot_private); + dpp->boot_private = NULL; + } + + if (dpp->timeout) { + l_timeout_remove(dpp->timeout); + dpp->timeout = NULL; + } + + if (dpp->config) { + dpp_configuration_free(dpp->config); + dpp->config = NULL; + } + + if (dpp->peer_asn1) { + l_free(dpp->peer_asn1); + dpp->peer_asn1 = NULL; + } + + if (dpp->own_asn1) { + l_free(dpp->own_asn1); + dpp->own_asn1 = NULL; + } + + if (dpp->frame_pending) { + l_free(dpp->frame_pending); + dpp->frame_pending = NULL; + } + + dpp->state = DPP_STATE_NOTHING; + dpp->pkex_version = 0; + + explicit_bzero(dpp->r_nonce, dpp->nonce_len); + explicit_bzero(dpp->i_nonce, dpp->nonce_len); + explicit_bzero(dpp->e_nonce, dpp->nonce_len); + explicit_bzero(dpp->ke, dpp->key_len); + 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); + + dpp_free_pending_pkex_data(dpp); + + dpp_free_auth_data(dpp); + + l_free(dpp); +} + +void dpp_sm_set_peer_bootstrap(struct dpp_sm *dpp, + struct l_ecc_point *public) +{ + dpp->peer_boot_public = public; + dpp->peer_asn1 = dpp_point_to_asn1(public, &dpp->peer_asn1_len); + + dpp_hash(L_CHECKSUM_SHA256, dpp->peer_boot_hash, 1, dpp->peer_asn1, + dpp->peer_asn1_len); +} + +const uint8_t *dpp_sm_get_own_asn1(struct dpp_sm *dpp, size_t *len) +{ + *len = dpp->own_asn1_len; + + return dpp->own_asn1; +} + +void dpp_sm_set_configuration(struct dpp_sm *dpp, + struct dpp_configuration *config) +{ + dpp->config = config; +} + +const struct dpp_configuration *dpp_sm_get_configuration(struct dpp_sm *dpp) +{ + return dpp->config; +} + +void dpp_sm_set_skip_presence(struct dpp_sm *dpp, bool skip) +{ + dpp->skip_presence = skip; +} + +void dpp_sm_set_channel(struct dpp_sm *dpp, uint8_t oper_class, uint8_t channel) +{ + dpp->channel[0] = oper_class; + dpp->channel[1] = channel; +} + +enum dpp_state dpp_sm_get_state(struct dpp_sm *dpp) +{ + return dpp->state; +} + +bool dpp_sm_start_initiator(struct dpp_sm *dpp) +{ + if (L_WARN_ON(!dpp->peer_boot_public)) + return false; + + dpp->initiator = true; + + /* Generate the keys for this protocol run */ + l_ecdh_generate_key_pair(dpp->curve, &dpp->proto_private, + &dpp->own_proto_public); + + l_getrandom(dpp->i_nonce, dpp->nonce_len); + + dpp->m = dpp_derive_k1(dpp->peer_boot_public, + dpp->proto_private, dpp->k1); + + if (dpp->config) + dpp->role = DPP_CAPABILITY_CONFIGURATOR; + else + dpp->role = DPP_CAPABILITY_ENROLLEE; + + dpp->state = DPP_STATE_PRESENCE; + + return true; +} + +bool dpp_sm_start_responder(struct dpp_sm *dpp) +{ + l_ecdh_generate_key_pair(dpp->curve, &dpp->proto_private, + &dpp->own_proto_public); + dpp->initiator = false; + + if (dpp->config) + dpp->role = DPP_CAPABILITY_CONFIGURATOR; + else + dpp->role = DPP_CAPABILITY_ENROLLEE; + + dpp->state = DPP_STATE_PRESENCE; + + return true; +} + +void dpp_sm_set_pkex_identifier(struct dpp_sm *dpp, const char *identifier) +{ + dpp->pkex_id = l_strdup(identifier); +} + +void dpp_sm_set_pkex_key(struct dpp_sm *dpp, const char *key) +{ + dpp->pkex_key = l_strdup(key); +} + +void dpp_sm_set_pkex_own_mac(struct dpp_sm *dpp, const uint8_t *mac) +{ + memcpy(dpp->pkex_own_mac, mac, 6); +} + +void dpp_sm_set_pkex_peer_mac(struct dpp_sm *dpp, const uint8_t *mac) +{ + memcpy(dpp->pkex_peer_mac, mac, 6); + + if (dpp->initiator) { + dpp->mac_responder = dpp->pkex_peer_mac; + dpp->mac_initiator = dpp->pkex_own_mac; + } else { + dpp->mac_initiator = dpp->pkex_peer_mac; + dpp->mac_responder = dpp->pkex_own_mac; + } +} + +bool dpp_sm_pkex_start_initiator(struct dpp_sm *dpp) +{ + _auto_(l_ecc_point_free) struct l_ecc_point *qi = NULL; + + if (!dpp->pkex_key) + return false; + + dpp->role = dpp->config ? DPP_CAPABILITY_CONFIGURATOR : + DPP_CAPABILITY_ENROLLEE; + + /* + * "DPP R2 devices are expected to use PKEXv1 by default" + * + * TODO: Support setting version (v2 required for TCP encapsulation) + */ + dpp->pkex_version = 1; + + if (!l_ecdh_generate_key_pair(dpp->curve, &dpp->pkex_private, + &dpp->pkex_public)) + return false; + + /* + * "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, + dpp->pkex_own_mac); + 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; + + dpp->initiator = true; + + dpp->mac_initiator = dpp->pkex_own_mac; + /* Won't know until we receive a response */ + dpp->mac_responder = NULL; + + dpp_reset_protocol_timer(dpp, DPP_AUTH_PROTO_TIMEOUT); + + /* Send exchange request */ + + return true; + +failed: + return false; +} + +bool dpp_sm_pkex_start_responder(struct dpp_sm *dpp) +{ + dpp->initiator = false; + + dpp->mac_responder = dpp->pkex_own_mac; + /* Won't know until we receive the first frame */ + dpp->mac_initiator = NULL; + + dpp->role = dpp->config ? DPP_CAPABILITY_CONFIGURATOR : + DPP_CAPABILITY_ENROLLEE; + dpp->state = DPP_STATE_PKEX_EXCHANGE; + dpp->pkex_version = 1; + + dpp_reset_protocol_timer(dpp, DPP_PKEX_PROTO_TIMEOUT); + + return true; +} + +void dpp_handle_rx(struct dpp_sm *dpp, const uint8_t *data, size_t len) +{ + /* Handle frame */ +} diff --git a/src/dpp-common.h b/src/dpp-common.h new file mode 100644 index 00000000..19ec45ac --- /dev/null +++ b/src/dpp-common.h @@ -0,0 +1,109 @@ +/* + * + * Wireless daemon for Linux + * + * Copyright (C) 2024 Locus Robotics + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +struct dpp_sm; +struct l_ecc_point; +struct l_ecc_scalar; + +enum dpp_state { + DPP_STATE_NOTHING, + DPP_STATE_PRESENCE, + DPP_STATE_PKEX_EXCHANGE, + DPP_STATE_PKEX_COMMIT_REVEAL, + DPP_STATE_AUTHENTICATING, + DPP_STATE_CONFIGURING, +}; + +enum dpp_capability { + DPP_CAPABILITY_ENROLLEE = 0x01, + DPP_CAPABILITY_CONFIGURATOR = 0x02, +}; + +enum dpp_event { + /* + * PEER_ACCEPTED indicates an initial DPP frame has been received and + * accepted. This could be either a PKEX or an auth frame when DPP is + * running as either a configurator or enrollee. This should be + * used by the encapsulating protocol to note the peer address (MAC + * or IP) and from then on only accept frames from this peer until DPP + * has completed. + */ + DPP_EVENT_PEER_ACCEPTED, + /* + * The authenticate request frame included a channel attribute. The + * encapsulating protocol must switch to this channel to continue the + * protocol (only applicable to 802.11 encapsulation). Event data is + * two bytes: [oper_class, channel] + */ + DPP_EVENT_CHANNEL_SWITCH, + /* + * A key corresponding to an identifier (set in event_data) is now + * required. The encapsulating protocol must retrieve the key and + * notify using dpp_sm_set_pkex_key(). + */ + DPP_EVENT_PKEX_KEY_REQUESTED, + DPP_EVENT_SUCCESS, + DPP_EVENT_FAILED, +}; + +typedef void (*dpp_event_cb_t)(enum dpp_event event, const void *event_data, + void *user_data); + +typedef void (*dpp_write_cb_t)(const uint8_t *data, size_t len, + void *user_data); + +struct dpp_sm *dpp_sm_new(dpp_event_cb_t event, + const struct l_ecc_point *boot_public, + const struct l_ecc_scalar *boot_private, + void *user_data); + +void dpp_sm_free(struct dpp_sm *dpp); + +void dpp_handle_rx(struct dpp_sm *dpp, const uint8_t *data, size_t len); +void dpp_sm_set_write_handler(struct dpp_sm *dpp, dpp_write_cb_t write); + +void dpp_sm_set_peer_bootstrap(struct dpp_sm *dpp, + struct l_ecc_point *public); +void dpp_sm_set_own_bootstrap(struct dpp_sm *dpp, struct l_ecc_point *public, + struct l_ecc_scalar *private); +const uint8_t *dpp_sm_get_own_asn1(struct dpp_sm *dpp, size_t *len); + +void dpp_sm_set_configuration(struct dpp_sm *dpp, + struct dpp_configuration *config); +const struct dpp_configuration *dpp_sm_get_configuration(struct dpp_sm *dpp); + +void dpp_sm_set_skip_presence(struct dpp_sm *dpp, bool skip); + +void dpp_sm_set_channel(struct dpp_sm *dpp, uint8_t oper_class, + uint8_t channel); +enum dpp_state dpp_sm_get_state(struct dpp_sm *dpp); + +bool dpp_sm_start_initiator(struct dpp_sm *dpp); +bool dpp_sm_start_responder(struct dpp_sm *dpp); + +void dpp_sm_set_pkex_identifier(struct dpp_sm *dpp, const char *identifier); +void dpp_sm_set_pkex_key(struct dpp_sm *dpp, const char *key); +void dpp_sm_set_pkex_own_mac(struct dpp_sm *dpp, const uint8_t *mac); +void dpp_sm_set_pkex_peer_mac(struct dpp_sm *dpp, const uint8_t *mac); + +bool dpp_sm_pkex_start_initiator(struct dpp_sm *dpp); +bool dpp_sm_pkex_start_responder(struct dpp_sm *dpp);