All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH v5 2/4] dpp: add DPP authentication protocol
@ 2021-12-17 21:18 James Prestwood
  0 siblings, 0 replies; 3+ messages in thread
From: James Prestwood @ 2021-12-17 21:18 UTC (permalink / raw)
  To: iwd

[-- Attachment #1: Type: text/plain, Size: 1715 bytes --]

On Fri, 2021-12-17 at 14:19 -0600, Denis Kenzior wrote:
> Hi James,
> 
> On 12/17/21 13:14, James Prestwood wrote:
> > This implements the DPP protocol used to authenticate to a
> > DPP configurator.
> > 
> > Note this is not a full implementation of the protocol and
> > there are a few missing features which will be added as
> > needed:
> > 
> >   - Mutual authentication (needed for BLE bootstrapping)
> >   - Configurator support
> >   - Initiator role
> > ---
> >   src/dpp.c | 491
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >   1 file changed, 491 insertions(+)
> > 
> > v5:
> >   * Updated use of wrap/unwrap APIs.
> >   * Better commented how AAD is used with wrapping/unwrapping
> > 
> 
> <snip>
> 
> > +static void dpp_free_auth_data(struct dpp_sm *dpp)
> > +{
> > +       if (dpp->proto_public) {
> > +               l_ecc_point_free(dpp->proto_public);
> > +               dpp->proto_public = NULL;
> > +       }
> > +
> > +       if (dpp->proto_private) {
> > +               l_ecc_scalar_free(dpp->proto_private);
> > +               dpp->proto_private = NULL;
> > +       }
> > +
> > +       if (dpp->i_proto_public) {
> > +               l_ecc_point_free(dpp->i_proto_public);
> > +               dpp->i_proto_public = NULL;
> > +       }
> 
> Should we be paranoid and explicit_bzero the nonces and keys?

Yes, for keys/nonces we can do this. I'm thinking we should also add
explicit_bzero to the l_ecc_point_free, as well as for scalars.

> 
> Applied, thanks.
> 
> Regards,
> -Denis


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH v5 2/4] dpp: add DPP authentication protocol
@ 2021-12-17 20:19 Denis Kenzior
  0 siblings, 0 replies; 3+ messages in thread
From: Denis Kenzior @ 2021-12-17 20:19 UTC (permalink / raw)
  To: iwd

[-- Attachment #1: Type: text/plain, Size: 1163 bytes --]

Hi James,

On 12/17/21 13:14, James Prestwood wrote:
> This implements the DPP protocol used to authenticate to a
> DPP configurator.
> 
> Note this is not a full implementation of the protocol and
> there are a few missing features which will be added as
> needed:
> 
>   - Mutual authentication (needed for BLE bootstrapping)
>   - Configurator support
>   - Initiator role
> ---
>   src/dpp.c | 491 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 491 insertions(+)
> 
> v5:
>   * Updated use of wrap/unwrap APIs.
>   * Better commented how AAD is used with wrapping/unwrapping
> 

<snip>

> +static void dpp_free_auth_data(struct dpp_sm *dpp)
> +{
> +	if (dpp->proto_public) {
> +		l_ecc_point_free(dpp->proto_public);
> +		dpp->proto_public = NULL;
> +	}
> +
> +	if (dpp->proto_private) {
> +		l_ecc_scalar_free(dpp->proto_private);
> +		dpp->proto_private = NULL;
> +	}
> +
> +	if (dpp->i_proto_public) {
> +		l_ecc_point_free(dpp->i_proto_public);
> +		dpp->i_proto_public = NULL;
> +	}

Should we be paranoid and explicit_bzero the nonces and keys?

Applied, thanks.

Regards,
-Denis

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH v5 2/4] dpp: add DPP authentication protocol
@ 2021-12-17 19:14 James Prestwood
  0 siblings, 0 replies; 3+ messages in thread
From: James Prestwood @ 2021-12-17 19:14 UTC (permalink / raw)
  To: iwd

[-- Attachment #1: Type: text/plain, Size: 16590 bytes --]

This implements the DPP protocol used to authenticate to a
DPP configurator.

Note this is not a full implementation of the protocol and
there are a few missing features which will be added as
needed:

 - Mutual authentication (needed for BLE bootstrapping)
 - Configurator support
 - Initiator role
---
 src/dpp.c | 491 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 491 insertions(+)

v5:
 * Updated use of wrap/unwrap APIs.
 * Better commented how AAD is used with wrapping/unwrapping

diff --git a/src/dpp.c b/src/dpp.c
index d9666ead..dd17cc47 100644
--- a/src/dpp.c
+++ b/src/dpp.c
@@ -41,6 +41,9 @@
 #include "src/ie.h"
 #include "src/iwd.h"
 #include "src/util.h"
+#include "src/crypto.h"
+#include "src/mpdu.h"
+#include "ell/useful.h"
 
 static uint32_t netdev_watch;
 static struct l_genl_family *nl80211;
@@ -49,6 +52,7 @@ static uint8_t broadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 enum dpp_state {
 	DPP_STATE_NOTHING,
 	DPP_STATE_PRESENCE,
+	DPP_STATE_AUTHENTICATING,
 };
 
 struct dpp_sm {
@@ -76,8 +80,38 @@ struct dpp_sm {
 	struct scan_freq_set *presence_list;
 
 	uint32_t offchannel_id;
+
+	uint8_t auth_addr[6];
+	uint8_t r_nonce[32];
+	uint8_t i_nonce[32];
+
+	uint64_t ke[L_ECC_MAX_DIGITS];
+	uint64_t k2[L_ECC_MAX_DIGITS];
+
+	struct l_ecc_scalar *proto_private;
+	struct l_ecc_point *proto_public;
+
+	struct l_ecc_point *i_proto_public;
 };
 
+static void dpp_free_auth_data(struct dpp_sm *dpp)
+{
+	if (dpp->proto_public) {
+		l_ecc_point_free(dpp->proto_public);
+		dpp->proto_public = NULL;
+	}
+
+	if (dpp->proto_private) {
+		l_ecc_scalar_free(dpp->proto_private);
+		dpp->proto_private = NULL;
+	}
+
+	if (dpp->i_proto_public) {
+		l_ecc_point_free(dpp->i_proto_public);
+		dpp->i_proto_public = NULL;
+	}
+}
+
 static void dpp_reset(struct dpp_sm *dpp)
 {
 	if (dpp->uri) {
@@ -96,6 +130,8 @@ static void dpp_reset(struct dpp_sm *dpp)
 	}
 
 	dpp->state = DPP_STATE_NOTHING;
+
+	dpp_free_auth_data(dpp);
 }
 
 static void dpp_free(struct dpp_sm *dpp)
@@ -167,6 +203,456 @@ static size_t dpp_build_header(const uint8_t *src, const uint8_t *dest,
 	return ptr - buf;
 }
 
+/*
+ * The Authentication protocol has a consistent use of AD components, and this
+ * use is defined in 6.3.1.4:
+ *
+ * "Invocations of AES-SIV in the DPP Authentication protocol that produce
+ * ciphertext that is part of an additional AES-SIV invocation do not use AAD;
+ * in other words, the number of AAD components is set to zero. 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 30, 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"
+ *
+ * In practice you see this as AD0 being some offset in the frame (offset to the
+ * OUI). For outgoing packets this is 26 bytes offset since the header is built
+ * manually. For incoming packets the offset is 2 bytes. The length is always
+ * 6 bytes for AD0.
+ *
+ * The AD1 data is always the start of the attributes, and length is the number
+ * of bytes from these attributes to wrapped data. e.g.
+ *
+ * ad1 = attrs
+ * ad1_len = ptr - attrs
+ */
+static void send_authenticate_response(struct dpp_sm *dpp, void *r_auth)
+{
+	uint8_t hdr[32];
+	uint8_t attrs[256];
+	uint8_t *ptr = attrs;
+	uint8_t status = DPP_STATUS_OK;
+	uint64_t r_proto_key[L_ECC_MAX_DIGITS * 2];
+	uint8_t version = 2;
+	uint8_t r_capabilities = 0x01;
+	struct iovec iov[3];
+	uint8_t wrapped2_plaintext[dpp->key_len + 4];
+	uint8_t wrapped2[dpp->key_len + 16 + 8];
+	size_t wrapped2_len;
+
+	l_ecc_point_get_data(dpp->proto_public, r_proto_key,
+				sizeof(r_proto_key));
+
+	iov[0].iov_len = dpp_build_header(netdev_get_address(dpp->netdev),
+				dpp->auth_addr,
+				DPP_FRAME_AUTHENTICATION_RESPONSE, hdr);
+	iov[0].iov_base = hdr;
+
+	ptr += dpp_append_attr(ptr, DPP_ATTR_STATUS, &status, 1);
+	ptr += dpp_append_attr(ptr, DPP_ATTR_RESPONDER_BOOT_KEY_HASH,
+				dpp->pub_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);
+
+	/* Wrap up secondary data (R-Auth) */
+	wrapped2_len = dpp_append_attr(wrapped2_plaintext,
+					DPP_ATTR_RESPONDER_AUTH_TAG,
+					r_auth, dpp->key_len);
+	/*
+	 * "Invocations of AES-SIV in the DPP Authentication protocol that
+	 * produce ciphertext that is part of an additional AES-SIV invocation
+	 * do not use AAD; in other words, the number of AAD components is set
+	 * to zero.""
+	 */
+	aes_siv_encrypt(dpp->ke, dpp->key_len, wrapped2_plaintext,
+					dpp->key_len + 4, NULL, 0, wrapped2);
+
+	wrapped2_len += 16;
+
+	ptr += dpp_append_wrapped_data(hdr + 26, 6, attrs, ptr - attrs,
+			ptr, sizeof(attrs), 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, 1, &r_capabilities,
+			DPP_ATTR_WRAPPED_DATA, wrapped2_len, wrapped2);
+
+	iov[1].iov_base = attrs;
+	iov[1].iov_len = ptr - attrs;
+
+	dpp_send_frame(netdev_get_wdev_id(dpp->netdev), iov, 2,
+				dpp->current_freq);
+}
+
+static void authenticate_confirm(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;
+	int status = -1;
+	const uint8_t *r_boot_hash = NULL;
+	const void *wrapped = NULL;
+	const uint8_t *i_auth = NULL;
+	size_t i_auth_len;
+	_auto_(l_free) uint8_t *unwrapped = NULL;
+	size_t wrapped_len = 0;
+	uint64_t i_auth_check[L_ECC_MAX_DIGITS];
+	const void *unwrap_key;
+	const void *ad0 = body + 2;
+	const void *ad1 = body + 8;
+
+	if (dpp->state != DPP_STATE_AUTHENTICATING)
+		return;
+
+	if (memcmp(from, dpp->auth_addr, 6))
+		return;
+
+	l_debug("authenticate confirm");
+
+	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:
+			status = l_get_u8(data);
+			break;
+		case DPP_ATTR_RESPONDER_BOOT_KEY_HASH:
+			r_boot_hash = data;
+			/*
+			 * Spec requires this, but does not mention if anything
+			 * is to be done with it.
+			 */
+			break;
+		case DPP_ATTR_INITIATOR_BOOT_KEY_HASH:
+			/* No mutual authentication */
+			break;
+		case DPP_ATTR_WRAPPED_DATA:
+			wrapped = data;
+			wrapped_len = len;
+			break;
+		default:
+			break;
+		}
+	}
+
+	if (!r_boot_hash || !wrapped) {
+		l_debug("Attributes missing from authenticate confirm");
+		return;
+	}
+
+	/*
+	 * "The Responder obtains the DPP Authentication Confirm frame and
+	 * checks the value of the DPP Status field. If the value of the DPP
+	 * Status field is STATUS_NOT_COMPATIBLE or STATUS_AUTH_FAILURE, the
+	 * Responder unwraps the wrapped data portion of the frame using k2"
+	 */
+	if (status == DPP_STATUS_OK)
+		unwrap_key = dpp->ke;
+	else if (status == DPP_STATUS_NOT_COMPATIBLE ||
+				status == DPP_STATUS_AUTH_FAILURE)
+		unwrap_key = dpp->k2;
+	else
+		goto auth_confirm_failed;
+
+	unwrapped = dpp_unwrap_attr(ad0, 6, ad1, wrapped - 4 - ad1,
+			unwrap_key, dpp->key_len, wrapped, wrapped_len,
+			&wrapped_len);
+	if (!unwrapped)
+		goto auth_confirm_failed;
+
+	if (status != DPP_STATUS_OK) {
+		/*
+		 * "If unwrapping is successful, the Responder should generate
+		 * an alert indicating the reason for the protocol failure."
+		 */
+		l_debug("Authentication failed due to status %s",
+				status == DPP_STATUS_NOT_COMPATIBLE ?
+				"NOT_COMPATIBLE" : "AUTH_FAILURE");
+		goto auth_confirm_failed;
+	}
+
+	dpp_attr_iter_init(&iter, unwrapped, wrapped_len);
+
+	while (dpp_attr_iter_next(&iter, &type, &len, &data)) {
+		switch (type) {
+		case DPP_ATTR_INITIATOR_AUTH_TAG:
+			i_auth = data;
+			i_auth_len = len;
+			break;
+		case DPP_ATTR_RESPONDER_NONCE:
+			/* Only if error */
+			break;
+		default:
+			break;
+		}
+	}
+
+	if (!i_auth || i_auth_len != dpp->key_len) {
+		l_debug("I-Auth missing from wrapped data");
+		goto auth_confirm_failed;
+	}
+
+	dpp_derive_i_auth(dpp->r_nonce, dpp->i_nonce, dpp->nonce_len,
+				dpp->proto_public, dpp->i_proto_public,
+				dpp->boot_public, i_auth_check);
+
+	if (memcmp(i_auth, i_auth_check, i_auth_len)) {
+		l_error("I-Auth did not verify");
+		goto auth_confirm_failed;
+	}
+
+	l_debug("Authentication successful");
+
+	return;
+
+auth_confirm_failed:
+	dpp->state = DPP_STATE_PRESENCE;
+	dpp_free_auth_data(dpp);
+}
+
+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 version = 2;
+	uint8_t r_capabilities = 0x01;
+	uint8_t s = status;
+	struct iovec iov[2];
+
+	iov[0].iov_len = dpp_build_header(netdev_get_address(dpp->netdev),
+				dpp->auth_addr,
+				DPP_FRAME_AUTHENTICATION_RESPONSE, hdr);
+	iov[0].iov_base = hdr;
+
+	ptr += dpp_append_attr(ptr, DPP_ATTR_STATUS, &s, 1);
+	ptr += dpp_append_attr(ptr, DPP_ATTR_RESPONDER_BOOT_KEY_HASH,
+				dpp->pub_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,
+			DPP_ATTR_INITIATOR_NONCE, dpp->nonce_len, dpp->i_nonce,
+			DPP_ATTR_RESPONDER_CAPABILITIES, 1, &r_capabilities);
+
+	iov[1].iov_base = attrs;
+	iov[1].iov_len = ptr - attrs;
+
+	dpp_send_frame(netdev_get_wdev_id(dpp->netdev), iov, 2,
+				dpp->current_freq);
+}
+
+static void authenticate_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 uint8_t *r_boot = NULL;
+	const uint8_t *i_boot = NULL;
+	const uint8_t *i_proto = NULL;
+	const void *wrapped = NULL;
+	const uint8_t *i_nonce = NULL;
+	size_t r_boot_len = 0, i_proto_len = 0, wrapped_len = 0;
+	size_t i_nonce_len = 0;
+	_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;
+	uint64_t k1[L_ECC_MAX_DIGITS];
+	uint64_t r_auth[L_ECC_MAX_DIGITS];
+	const void *ad0 = body + 2;
+	const void *ad1 = body + 8;
+
+	if (dpp->state != DPP_STATE_PRESENCE)
+		return;
+
+	l_debug("authenticate request");
+
+	dpp_attr_iter_init(&iter, body + 8, body_len - 8);
+
+	while (dpp_attr_iter_next(&iter, &type, &len, &data)) {
+		switch (type) {
+		case DPP_ATTR_INITIATOR_BOOT_KEY_HASH:
+			i_boot = data;
+			/*
+			 * This attribute is required by the spec, but only
+			 * used for mutual authentication.
+			 */
+			break;
+		case DPP_ATTR_RESPONDER_BOOT_KEY_HASH:
+			r_boot = data;
+			r_boot_len = len;
+			break;
+		case DPP_ATTR_INITIATOR_PROTOCOL_KEY:
+			i_proto = data;
+			i_proto_len = len;
+			break;
+		case DPP_ATTR_WRAPPED_DATA:
+			/* I-Nonce/I-Capabilities part of wrapped data */
+			wrapped = data;
+			wrapped_len = len;
+			break;
+
+		/* Optional attributes */
+		case DPP_ATTR_PROTOCOL_VERSION:
+			if (l_get_u8(data) != 2) {
+				l_debug("Protocol version did not match");
+				return;
+			}
+
+			break;
+		/*
+		 * TODO: Go on this channel for remainder of auth protocol.
+		 *
+		 * "the Responder determines whether it can use the requested
+		 * channel for the following exchanges. If so, it sends the DPP
+		 * Authentication Response frame on that channel. If not, it
+		 * discards the DPP Authentication Request frame without
+		 * replying to it."
+		 *
+		 * For the time being this feature is not being implemented and
+		 * the frame will be dropped.
+		 */
+		case DPP_ATTR_CHANNEL:
+			return;
+		default:
+			break;
+		}
+	}
+
+	if (!r_boot || !i_boot || !i_proto || !wrapped)
+		goto auth_request_failed;
+
+	if (r_boot_len != 32 || memcmp(dpp->pub_boot_hash,
+					r_boot, r_boot_len)) {
+		l_debug("Responder boot key hash failed to verify");
+		goto auth_request_failed;
+	}
+
+	dpp->i_proto_public = l_ecc_point_from_data(dpp->curve,
+						L_ECC_POINT_TYPE_FULL,
+						i_proto, i_proto_len);
+	if (!dpp->i_proto_public) {
+		l_debug("Initiators protocol key invalid");
+		goto auth_request_failed;
+	}
+
+	m = dpp_derive_k1(dpp->i_proto_public, dpp->boot_private, k1);
+	if (!m)
+		goto auth_request_failed;
+
+	unwrapped = dpp_unwrap_attr(ad0, 6, ad1, wrapped - 4 - ad1,
+			k1, dpp->key_len, wrapped, wrapped_len, &wrapped_len);
+	if (!unwrapped)
+		goto auth_request_failed;
+
+	dpp_attr_iter_init(&iter, unwrapped, wrapped_len);
+
+	while (dpp_attr_iter_next(&iter, &type, &len, &data)) {
+		switch (type) {
+		case DPP_ATTR_INITIATOR_NONCE:
+			i_nonce = data;
+			i_nonce_len = len;
+			break;
+		case DPP_ATTR_INITIATOR_CAPABILITIES:
+			/*
+			 * "If the Responder is not capable of supporting the
+			 * role indicated by the Initiator, it shall respond
+			 * with a DPP Authentication Response frame indicating
+			 * failure by adding the DPP Status field set to
+			 * STATUS_NOT_COMPATIBLE"
+			 */
+			if (!(l_get_u8(data) & 0x2)) {
+				l_debug("Initiator is not configurator");
+
+				dpp_auth_request_failed(dpp,
+						DPP_STATUS_NOT_COMPATIBLE, k1);
+				goto auth_request_failed;
+			}
+
+			break;
+		default:
+			break;
+		}
+	}
+
+	if (i_nonce_len != dpp->nonce_len) {
+		l_debug("I-Nonce has unexpected length %lu", i_nonce_len);
+		goto auth_request_failed;
+	}
+
+	memcpy(dpp->i_nonce, i_nonce, i_nonce_len);
+
+	/* Derive keys k2, ke, and R-Auth for authentication response */
+
+	l_ecdh_generate_key_pair(dpp->curve, &dpp->proto_private,
+					&dpp->proto_public);
+
+	n = dpp_derive_k2(dpp->i_proto_public, dpp->proto_private, dpp->k2);
+	if (!n)
+		goto auth_request_failed;
+
+	l_getrandom(dpp->r_nonce, dpp->nonce_len);
+
+	if (!dpp_derive_ke(dpp->i_nonce, dpp->r_nonce, m, n, dpp->ke))
+		goto auth_request_failed;
+
+	if (!dpp_derive_r_auth(dpp->i_nonce, dpp->r_nonce, dpp->nonce_len,
+				dpp->i_proto_public, dpp->proto_public,
+				dpp->boot_public, r_auth))
+		goto auth_request_failed;
+
+	memcpy(dpp->auth_addr, from, 6);
+
+	dpp->state = DPP_STATE_AUTHENTICATING;
+
+	send_authenticate_response(dpp, r_auth);
+
+	return;
+
+auth_request_failed:
+	dpp->state = DPP_STATE_PRESENCE;
+	dpp_free_auth_data(dpp);
+}
+
+static void dpp_handle_auth_frame(const struct mmpdu_header *frame,
+				const void *body, size_t body_len,
+				int rssi, void *user_data)
+{
+	struct dpp_sm *dpp = user_data;
+	const uint8_t *ptr;
+
+	/*
+	 * Both handlers offset by 8 bytes to reach the beginning of the DPP
+	 * attributes. Easier checking this in one place, which also covers the
+	 * frame type byte.
+	 */
+	if (body_len < 8)
+		return;
+
+	ptr = body + 7;
+
+	switch (*ptr) {
+	case DPP_FRAME_AUTHENTICATION_REQUEST:
+		authenticate_request(dpp, frame->address_2, body, body_len);
+		break;
+	case DPP_FRAME_AUTHENTICATION_CONFIRM:
+		authenticate_confirm(dpp, frame->address_2, body, body_len);
+		break;
+	default:
+		l_debug("Unhandled DPP frame %u", *ptr);
+		break;
+	}
+}
+
 static void dpp_presence_announce(struct dpp_sm *dpp)
 {
 	struct netdev *netdev = dpp->netdev;
@@ -206,6 +692,7 @@ static void dpp_create(struct netdev *netdev)
 {
 	struct l_dbus *dbus = dbus_get_bus();
 	struct dpp_sm *dpp = l_new(struct dpp_sm, 1);
+	uint8_t dpp_prefix[] = { 0x04, 0x09, 0x50, 0x6f, 0x9a, 0x1a, 0x01 };
 
 	dpp->netdev = netdev;
 	dpp->state = DPP_STATE_NOTHING;
@@ -224,6 +711,10 @@ static void dpp_create(struct netdev *netdev)
 
 	l_dbus_object_add_interface(dbus, netdev_get_path(netdev),
 					IWD_DPP_INTERFACE, dpp);
+
+	frame_watch_add(netdev_get_wdev_id(netdev), 0, 0x00d0, dpp_prefix,
+				sizeof(dpp_prefix), dpp_handle_auth_frame,
+				dpp, NULL);
 }
 
 static void dpp_netdev_watch(struct netdev *netdev,
-- 
2.31.1

^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2021-12-17 21:18 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-12-17 21:18 [PATCH v5 2/4] dpp: add DPP authentication protocol James Prestwood
  -- strict thread matches above, loose matches on Subject: below --
2021-12-17 20:19 Denis Kenzior
2021-12-17 19:14 James Prestwood

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.