[PATCH] DPP: Check PKEX Encrypted Key attribute length against the curve
alepacheco99 at gmail.com
alepacheco99 at gmail.com
Thu Oct 15 17:19:23 PDT 2026
dpp_pkex_rx_exchange_req() and dpp_pkex_rx_exchange_resp() passed the
Encrypted Key attribute to crypto_ec_point_from_bin() after checking
only that its length was even and nonzero (and, for the request, not
larger than twice the maximum coordinate length).
crypto_ec_point_from_bin() reads 2 * prime_len octets for the x and y
coordinates, so a shorter attribute resulted in reading beyond the
attribute and, when it was the last one, beyond the received frame. An
oversized attribute in the response also caused an incorrect N.x length
to be used when deriving z.
Require the attribute to be exactly 2 * prime_len octets, as is already
done for the Bootstrapping Key attribute in the PKEX Commit-Reveal
messages.
Add module tests for PKEX Exchange Request and Response processing
rejecting an Encrypted Key attribute of the wrong length.
Signed-off-by: Alejandro Pacheco <alepacheco99 at gmail.com>
---
src/common/common_module_tests.c | 168 +++++++++++++++++++++++++++++++
src/common/dpp_pkex.c | 5 +-
2 files changed, 170 insertions(+), 3 deletions(-)
diff --git a/src/common/common_module_tests.c b/src/common/common_module_tests.c
index 74a0ea368..8274b5db8 100644
--- a/src/common/common_module_tests.c
+++ b/src/common/common_module_tests.c
@@ -17,6 +17,7 @@
#include "gas.h"
#include "wpa_common.h"
#include "sae.h"
+#include "dpp.h"
struct ieee802_11_parse_test_data {
@@ -781,6 +782,172 @@ static int pasn_tests(void)
}
+#ifdef CONFIG_DPP
+
+static struct wpabuf * dpp_pkex_test_key_len(const struct wpabuf *msg,
+ int delta)
+{
+ const u8 *pos = wpabuf_head_u8(msg) + 8;
+ const u8 *end = wpabuf_head_u8(msg) + wpabuf_len(msg);
+ struct wpabuf *buf, *ret;
+
+ buf = wpabuf_alloc(wpabuf_len(msg) + 2);
+ if (!buf)
+ return NULL;
+
+ while (end - pos >= 4) {
+ u16 id = WPA_GET_LE16(pos);
+ u16 alen = WPA_GET_LE16(pos + 2);
+
+ pos += 4;
+ if (alen > end - pos)
+ break;
+ wpabuf_put_le16(buf, id);
+ if (id == DPP_ATTR_ENCRYPTED_KEY) {
+ wpabuf_put_le16(buf, alen + delta);
+ if (delta < 0) {
+ wpabuf_put_data(buf, pos, alen + delta);
+ } else {
+ wpabuf_put_data(buf, pos, alen);
+ wpabuf_put(buf, delta);
+ }
+ } else {
+ wpabuf_put_le16(buf, alen);
+ wpabuf_put_data(buf, pos, alen);
+ }
+ pos += alen;
+ }
+
+ ret = wpabuf_dup(buf);
+ wpabuf_free(buf);
+ return ret;
+}
+
+
+static int dpp_pkex_tests(void)
+{
+ struct dpp_global_config config;
+ struct dpp_global *dpp;
+ struct dpp_bootstrap_info *bi_i, *bi_r;
+ struct dpp_pkex *init = NULL, *resp = NULL;
+ struct wpabuf *buf = NULL, *msg = NULL;
+ const u8 addr_i[ETH_ALEN] = { 0x02, 0x00, 0x00, 0x00, 0x00, 0x01 };
+ const u8 addr_r[ETH_ALEN] = { 0x02, 0x00, 0x00, 0x00, 0x00, 0x02 };
+ const char *code = "pkex test code";
+ const int delta[] = { -2, 2 };
+ unsigned int i;
+ int ret = -1;
+
+ wpa_printf(MSG_INFO, "DPP PKEX tests");
+
+ os_memset(&config, 0, sizeof(config));
+ dpp = dpp_global_init(&config);
+ if (!dpp)
+ return -1;
+ bi_i = dpp_bootstrap_get_id(dpp, dpp_bootstrap_gen(
+ dpp, "type=pkex curve=prime256v1"));
+ bi_r = dpp_bootstrap_get_id(dpp, dpp_bootstrap_gen(
+ dpp, "type=pkex curve=prime256v1"));
+ if (!bi_i || !bi_r)
+ goto fail;
+
+ for (i = 0; i <= ARRAY_SIZE(delta); i++) {
+ init = dpp_pkex_init(NULL, bi_i, addr_i, NULL, code,
+ os_strlen(code), false);
+ if (!init)
+ goto fail;
+
+ if (i < ARRAY_SIZE(delta)) {
+ buf = dpp_pkex_test_key_len(init->exchange_req,
+ delta[i]);
+ if (!buf)
+ goto fail;
+ resp = dpp_pkex_rx_exchange_req(NULL, bi_r, addr_r,
+ addr_i, NULL, code,
+ os_strlen(code),
+ wpabuf_head(buf),
+ wpabuf_len(buf), false);
+ if (resp) {
+ wpa_printf(MSG_ERROR,
+ "DPP PKEX: Exchange Request with Encrypted Key length %d accepted",
+ (int) (2 * bi_r->curve->prime_len) +
+ delta[i]);
+ goto fail;
+ }
+ wpabuf_free(buf);
+ buf = NULL;
+ }
+
+ resp = dpp_pkex_rx_exchange_req(
+ NULL, bi_r, addr_r, addr_i, NULL, code,
+ os_strlen(code), wpabuf_head_u8(init->exchange_req) + 8,
+ wpabuf_len(init->exchange_req) - 8, false);
+ if (!resp || !resp->exchange_resp) {
+ wpa_printf(MSG_ERROR,
+ "DPP PKEX: Valid Exchange Request rejected");
+ goto fail;
+ }
+
+ if (i < ARRAY_SIZE(delta)) {
+ buf = dpp_pkex_test_key_len(resp->exchange_resp,
+ delta[i]);
+ if (!buf)
+ goto fail;
+ msg = dpp_pkex_rx_exchange_resp(init, addr_r,
+ wpabuf_head(buf),
+ wpabuf_len(buf));
+ if (msg) {
+ wpa_printf(MSG_ERROR,
+ "DPP PKEX: Exchange Response with Encrypted Key length %d accepted",
+ (int) (2 * bi_i->curve->prime_len) +
+ delta[i]);
+ goto fail;
+ }
+ } else {
+ msg = dpp_pkex_rx_exchange_resp(
+ init, addr_r,
+ wpabuf_head_u8(resp->exchange_resp) + 8,
+ wpabuf_len(resp->exchange_resp) - 8);
+ if (!msg) {
+ wpa_printf(MSG_ERROR,
+ "DPP PKEX: Valid Exchange Response rejected");
+ goto fail;
+ }
+ }
+
+ wpabuf_free(buf);
+ buf = NULL;
+ wpabuf_free(msg);
+ msg = NULL;
+ dpp_pkex_free(init);
+ init = NULL;
+ dpp_pkex_free(resp);
+ resp = NULL;
+ }
+
+ ret = 0;
+fail:
+ wpabuf_free(buf);
+ wpabuf_free(msg);
+ dpp_pkex_free(init);
+ dpp_pkex_free(resp);
+ dpp_global_deinit(dpp);
+ return ret;
+}
+
+#endif /* CONFIG_DPP */
+
+
+static int dpp_tests(void)
+{
+#ifdef CONFIG_DPP
+ if (dpp_pkex_tests() < 0)
+ return -1;
+#endif /* CONFIG_DPP */
+ return 0;
+}
+
+
int common_module_tests(void)
{
int ret = 0;
@@ -792,6 +959,7 @@ int common_module_tests(void)
sae_tests() < 0 ||
sae_pk_tests() < 0 ||
pasn_tests() < 0 ||
+ dpp_tests() < 0 ||
rsn_ie_parse_tests() < 0)
ret = -1;
diff --git a/src/common/dpp_pkex.c b/src/common/dpp_pkex.c
index dca0d8d39..7f6659638 100644
--- a/src/common/dpp_pkex.c
+++ b/src/common/dpp_pkex.c
@@ -432,8 +432,7 @@ struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx,
/* M in Encrypted Key attribute */
attr_key = dpp_get_attr(buf, len, DPP_ATTR_ENCRYPTED_KEY,
&attr_key_len);
- if (!attr_key || attr_key_len & 0x01 || attr_key_len < 2 ||
- attr_key_len / 2 > DPP_MAX_SHARED_SECRET_LEN) {
+ if (!attr_key || attr_key_len != 2 * curve->prime_len) {
wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL
"Missing Encrypted Key attribute");
return NULL;
@@ -789,7 +788,7 @@ struct wpabuf * dpp_pkex_rx_exchange_resp(struct
dpp_pkex *pkex,
/* N in Encrypted Key attribute */
attr_key = dpp_get_attr(buf, buflen, DPP_ATTR_ENCRYPTED_KEY,
&attr_key_len);
- if (!attr_key || attr_key_len & 0x01 || attr_key_len < 2) {
+ if (!attr_key || attr_key_len != 2 * curve->prime_len) {
dpp_pkex_fail(pkex, "Missing Encrypted Key attribute");
return NULL;
}
--
2.48.1
More information about the Hostap
mailing list