[RFC v2 41/99] NAN: Handle security in NDP processing

Andrei Otcheretianski andrei.otcheretianski at intel.com
Tue Dec 23 03:51:45 PST 2025


From: Ilan Peer <ilan.peer at intel.com>

- Handle security related attributes after NDP attribute processing
  is done.
- Set the security present flag in the NDP control field
  when security is negotiated.

Signed-off-by: Ilan Peer <ilan.peer at intel.com>
---
 src/nan/nan_ndp.c | 135 +++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 117 insertions(+), 18 deletions(-)

diff --git a/src/nan/nan_ndp.c b/src/nan/nan_ndp.c
index 3a37751a7a..9d8ca08ce2 100644
--- a/src/nan/nan_ndp.c
+++ b/src/nan/nan_ndp.c
@@ -133,6 +133,7 @@ int nan_ndp_setup_req(struct nan_data *nan, struct nan_peer *peer,
 		return ret;
 	}
 
+	nan_sec_reset(nan, &peer->ndp_setup.sec);
 	nan_ndp_set_state(nan, &peer->ndp_setup, NAN_NDP_STATE_START);
 	peer->ndp_setup.status = NAN_NDP_STATUS_CONTINUED;
 	return 0;
@@ -209,6 +210,7 @@ static int nan_ndp_attr_handle_req(struct nan_data *nan, struct nan_peer *peer,
 	struct nan_ndp_setup *ndp_setup = &peer->ndp_setup;
 	u16 exp_len = sizeof(struct ieee80211_ndp);
 	u8 publish_inst_id;
+	int ret;
 
 	if (ndp_setup->ndp) {
 		wpa_printf(MSG_DEBUG,
@@ -248,6 +250,7 @@ static int nan_ndp_attr_handle_req(struct nan_data *nan, struct nan_peer *peer,
 	if (!ndp_setup->ndp)
 		return -1;
 
+	nan_sec_reset(nan, &peer->ndp_setup.sec);
 	nan_ndp_set_state(nan, ndp_setup, NAN_NDP_STATE_REQ_RECV);
 
 	ndp_setup->status = NAN_NDP_STATUS_CONTINUED;
@@ -255,15 +258,16 @@ static int nan_ndp_attr_handle_req(struct nan_data *nan, struct nan_peer *peer,
 		!!(ndp_attr->ndp_ctrl & NAN_NDP_CTRL_CONFIRM_REQUIRED);
 	ndp_setup->dialog_token = ndp_attr->dialog_token;
 	ndp_setup->publish_inst_id = publish_inst_id;
+	ndp_setup->sec.present =
+		!!(ndp_attr->ndp_ctrl & NAN_NDP_CTRL_SECURITY_PRESENT);
 
 	/* Handle service specific information */
 	ndp_len -= exp_len;
 
 	if (ndp_attr->ndp_ctrl & NAN_NDP_CTRL_SPEC_INFO_PRESENT && ndp_len) {
-		int ret;
-
 		wpa_printf(MSG_DEBUG,
 			   "NAN: NDP: req: Handle NDP service specific information");
+
 		ret = nan_ndp_ssi(nan, &peer->ndp_setup,
 				  (u8 *)ndp_attr->optional + 1,
 				  ndp_len);
@@ -282,6 +286,7 @@ static int nan_ndp_attr_handle_res(struct nan_data *nan, struct nan_peer *peer,
 {
 	struct nan_ndp_setup *ndp_setup = &peer->ndp_setup;
 	u16 opt_len;
+	u8 sec_present;
 
 	if (!ndp_setup->ndp) {
 		wpa_printf(MSG_DEBUG,
@@ -355,10 +360,17 @@ static int nan_ndp_attr_handle_res(struct nan_data *nan, struct nan_peer *peer,
 		goto store_ssi;
 	}
 
-	if (((ndp_attr->ndp_ctrl & NAN_NDP_CTRL_SECURITY_PRESENT) ||
-	     ndp_setup->conf_req) && status != NAN_NDP_STATUS_CONTINUED) {
+	sec_present = !!(ndp_attr->ndp_ctrl & NAN_NDP_CTRL_SECURITY_PRESENT);
+	if (ndp_setup->sec.present != sec_present) {
+		wpa_printf(MSG_DEBUG,
+			   "NAN: NDP: Security present mismatch");
+		return -1;
+	}
+
+	if ((sec_present || ndp_setup->conf_req) &&
+	    status != NAN_NDP_STATUS_CONTINUED) {
 		wpa_printf(MSG_DEBUG,
-			   "NAN: NDP: Security present and status != continue");
+			   "NAN: NDP: Security present or confirm required and status != continue");
 		return -1;
 	}
 
@@ -407,6 +419,7 @@ static int nan_ndp_attr_handle_confirm(struct nan_data *nan,
 				       u8 status)
 {
 	struct nan_ndp_setup *ndp_setup = &peer->ndp_setup;
+	u8 sec_present;
 
 	if (!ndp_setup->ndp) {
 		wpa_printf(MSG_DEBUG,
@@ -441,8 +454,14 @@ static int nan_ndp_attr_handle_confirm(struct nan_data *nan,
 		return -1;
 	}
 
-	if ((ndp_attr->ndp_ctrl & NAN_NDP_CTRL_SECURITY_PRESENT) &&
-	    status != NAN_NDP_STATUS_CONTINUED) {
+	sec_present = !!(ndp_attr->ndp_ctrl & NAN_NDP_CTRL_SECURITY_PRESENT);
+	if (ndp_setup->sec.present != sec_present) {
+		wpa_printf(MSG_DEBUG,
+			   "NAN: NDP: confirm security present mismatch");
+		return -1;
+	}
+
+	if (sec_present && status != NAN_NDP_STATUS_CONTINUED) {
 		wpa_printf(MSG_DEBUG,
 			   "NAN: NDP: confirm: status != continue with security");
 		return -1;
@@ -457,10 +476,9 @@ static int nan_ndp_attr_handle_confirm(struct nan_data *nan,
 
 	ndp_setup->status = status;
 
-	/* TODO: handle security */
-	if (status == NAN_NDP_STATUS_ACCEPTED)
+	if (sec_present)
 		nan_ndp_set_state(nan, &peer->ndp_setup,
-				  NAN_NDP_STATE_DONE);
+				  NAN_NDP_STATE_CON_RECV);
 	else
 		nan_ndp_set_state(nan, &peer->ndp_setup,
 				  NAN_NDP_STATE_DONE);
@@ -484,6 +502,62 @@ static struct nan_ndp * nan_ndp_find_ndp(struct nan_peer *peer,
 }
 
 
+static int nan_ndp_attr_sec_install(struct nan_data *nan, struct nan_peer *peer,
+				    struct ieee80211_ndp *ndp_attr, u8 status)
+{
+	struct nan_ndp_setup *ndp_setup = &peer->ndp_setup;
+	u8 sec_present;
+
+	if (!ndp_setup->ndp) {
+		wpa_printf(MSG_DEBUG,
+			   "NAN: NDP: sec install while no NDP WIP with peer");
+		return -1;
+	}
+
+	if (ndp_setup->state != NAN_NDP_STATE_CON_SENT) {
+		wpa_printf(MSG_DEBUG,
+			   "NAN: NDP: sec install while not expecting one");
+
+		if (ndp_setup->state != NAN_NDP_STATE_RES_RECV ||
+		    ndp_setup->status != NAN_NDP_STATUS_CONTINUED)
+			return -1;
+
+		/* Due to races with the driver, it is possible that the
+		 * install is received before an ACK is indicated. Allow the
+		 * processing of the attribute, and if all parameters are OK,
+		 * fast forward the state machine below.
+		 */
+		wpa_printf(MSG_DEBUG,
+			   "NAN: NDP: sec install received before Tx status.");
+	}
+
+	if (ndp_setup->ndp->ndp_id != ndp_attr->ndp_id ||
+	    ndp_setup->dialog_token != ndp_attr->dialog_token ||
+	    os_memcmp(ndp_setup->ndp->init_ndi, ndp_attr->initiator_ndi,
+		      ETH_ALEN)) {
+		wpa_printf(MSG_DEBUG,
+			   "NAN: NDP: sec install: invalid NDP parameters");
+		return -1;
+	}
+
+	sec_present = !!(ndp_attr->ndp_ctrl & NAN_NDP_CTRL_SECURITY_PRESENT);
+	if (ndp_setup->sec.present != sec_present) {
+		wpa_printf(MSG_DEBUG,
+			   "NAN: NDP: sec install: security present mismatch");
+		return -1;
+	}
+
+	if (status != NAN_NDP_STATUS_ACCEPTED) {
+		wpa_printf(MSG_DEBUG,
+			   "NAN: NDP: sec install: status != ACCEPTED");
+		return -1;
+	}
+
+	nan_ndp_set_state(nan, &peer->ndp_setup, NAN_NDP_STATE_DONE);
+	return 0;
+}
+
+
 static int nan_ndp_attr_handle_term(struct nan_data *nan, struct nan_peer *peer,
 				    struct ieee80211_ndp *ndp_attr, u8 status)
 {
@@ -570,6 +644,7 @@ int nan_ndp_handle_ndp_attr(struct nan_data *nan, struct nan_peer *peer,
 {
 	struct ieee80211_ndp *ndp_attr;
 	u8 type, status;
+	int ret;
 
 	if (!msg || !peer || !msg->attrs.ndp)
 		return -1;
@@ -596,22 +671,43 @@ int nan_ndp_handle_ndp_attr(struct nan_data *nan, struct nan_peer *peer,
 
 	switch (type) {
 	case NAN_NDP_TYPE_REQUEST:
-		return nan_ndp_attr_handle_req(nan, peer, ndp_attr,
-					       msg->attrs.ndp_len, status);
+		ret = nan_ndp_attr_handle_req(nan, peer, ndp_attr,
+					      msg->attrs.ndp_len,
+					      status);
+		break;
 	case NAN_NDP_TYPE_RESPONSE:
-		return nan_ndp_attr_handle_res(nan, peer, ndp_attr,
-					       msg->attrs.ndp_len,
-					       status);
+		ret = nan_ndp_attr_handle_res(nan, peer, ndp_attr,
+					      msg->attrs.ndp_len,
+					      status);
+		break;
 	case NAN_NDP_TYPE_CONFIRM:
-		return nan_ndp_attr_handle_confirm(nan, peer, ndp_attr, status);
+		ret = nan_ndp_attr_handle_confirm(nan, peer, ndp_attr, status);
+		break;
 	case NAN_NDP_TYPE_SECURITY_INSTALL:
-		/* TODO: Handle security */
-		return -1;
+		ret = nan_ndp_attr_sec_install(nan, peer, ndp_attr, status);
+		break;
 	case NAN_NDP_TYPE_TERMINATE:
 		return nan_ndp_attr_handle_term(nan, peer, ndp_attr, status);
 	default:
 		return -1;
 	}
+
+	/* error or no security ... we are done */
+	if (ret || !peer->ndp_setup.sec.present ||
+	    peer->ndp_setup.status == NAN_NDP_STATUS_REJECTED)
+		return ret;
+
+	ret = nan_sec_rx(nan, peer, msg);
+	if (ret)
+		return ret;
+
+	/* processing of confirm is successful, so to the overall status is
+	 * success
+	 */
+	if (type == NAN_NDP_TYPE_CONFIRM)
+		peer->ndp_setup.status = NAN_NDP_STATUS_ACCEPTED;
+
+	return 0;
 }
 
 
@@ -672,6 +768,9 @@ int nan_ndp_add_ndp_attr(struct nan_data *nan, struct nan_peer *peer,
 		return 0;
 	}
 
+	if (ndp_setup->sec.present)
+		ndp_ctrl |= NAN_NDP_CTRL_SECURITY_PRESENT;
+
 	wpabuf_put_u8(buf, NAN_ATTR_NDP);
 	len_ptr = wpabuf_put(buf, 2);
 
-- 
2.49.0




More information about the Hostap mailing list