Extend the NAN Subscribe and Publish methods to allow p2p=1 to be specified to include P2P attributes in a P2P IE to be added into the NAN Element Container attribute. Signed-off-by: Shivani Baranwal <quic_shivbara@xxxxxxxxxxx> diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index 92df81c6c..2fb5f6960 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -3690,6 +3690,7 @@ static int hostapd_ctrl_nan_publish(struct hostapd_data *hapd, char *cmd, struct wpabuf *ssi = NULL; int ret = -1; enum nan_service_protocol_type srv_proto_type = 0; + bool p2p = false; os_memset(¶ms, 0, sizeof(params)); /* USD shall use both solicited and unsolicited transmissions */ @@ -3723,6 +3724,11 @@ static int hostapd_ctrl_nan_publish(struct hostapd_data *hapd, char *cmd, continue; } + if (os_strcmp(token, "p2p=1") == 0) { + p2p = true; + continue; + } + if (os_strcmp(token, "solicited=0") == 0) { params.solicited = false; continue; @@ -3744,7 +3750,7 @@ static int hostapd_ctrl_nan_publish(struct hostapd_data *hapd, char *cmd, } publish_id = hostapd_nan_usd_publish(hapd, service_name, srv_proto_type, - ssi, ¶ms); + ssi, ¶ms, p2p); if (publish_id > 0) ret = os_snprintf(buf, buflen, "%d", publish_id); fail: @@ -3827,6 +3833,7 @@ static int hostapd_ctrl_nan_subscribe(struct hostapd_data *hapd, char *cmd, struct wpabuf *ssi = NULL; int ret = -1; enum nan_service_protocol_type srv_proto_type = 0; + bool p2p = false; os_memset(¶ms, 0, sizeof(params)); @@ -3860,6 +3867,11 @@ static int hostapd_ctrl_nan_subscribe(struct hostapd_data *hapd, char *cmd, continue; } + if (os_strcmp(token, "p2p=1") == 0) { + p2p = true; + continue; + } + wpa_printf(MSG_INFO, "CTRL: Invalid NAN_SUBSCRIBE parameter: %s", token); @@ -3868,7 +3880,7 @@ static int hostapd_ctrl_nan_subscribe(struct hostapd_data *hapd, char *cmd, subscribe_id = hostapd_nan_usd_subscribe(hapd, service_name, srv_proto_type, ssi, - ¶ms); + ¶ms, p2p); if (subscribe_id > 0) ret = os_snprintf(buf, buflen, "%d", subscribe_id); fail: diff --git a/src/ap/nan_usd_ap.c b/src/ap/nan_usd_ap.c index 70c6139fd..570abfce0 100644 --- a/src/ap/nan_usd_ap.c +++ b/src/ap/nan_usd_ap.c @@ -192,7 +192,7 @@ void hostapd_nan_usd_flush(struct hostapd_data *hapd) int hostapd_nan_usd_publish(struct hostapd_data *hapd, const char *service_name, enum nan_service_protocol_type srv_proto_type, const struct wpabuf *ssi, - struct nan_publish_params *params) + struct nan_publish_params *params, bool p2p) { int publish_id; struct wpabuf *elems = NULL; @@ -201,7 +201,7 @@ int hostapd_nan_usd_publish(struct hostapd_data *hapd, const char *service_name, return -1; publish_id = nan_de_publish(hapd->nan_de, service_name, srv_proto_type, - ssi, elems, params); + ssi, elems, params, p2p); wpabuf_free(elems); return publish_id; } @@ -231,7 +231,7 @@ int hostapd_nan_usd_subscribe(struct hostapd_data *hapd, const char *service_name, enum nan_service_protocol_type srv_proto_type, const struct wpabuf *ssi, - struct nan_subscribe_params *params) + struct nan_subscribe_params *params, bool p2p) { int subscribe_id; struct wpabuf *elems = NULL; @@ -240,7 +240,7 @@ int hostapd_nan_usd_subscribe(struct hostapd_data *hapd, return -1; subscribe_id = nan_de_subscribe(hapd->nan_de, service_name, - srv_proto_type, ssi, elems, params); + srv_proto_type, ssi, elems, params, p2p); wpabuf_free(elems); return subscribe_id; } diff --git a/src/ap/nan_usd_ap.h b/src/ap/nan_usd_ap.h index 58ff5fc48..0571643c6 100644 --- a/src/ap/nan_usd_ap.h +++ b/src/ap/nan_usd_ap.h @@ -21,7 +21,7 @@ void hostapd_nan_usd_flush(struct hostapd_data *hapd); int hostapd_nan_usd_publish(struct hostapd_data *hapd, const char *service_name, enum nan_service_protocol_type srv_proto_type, const struct wpabuf *ssi, - struct nan_publish_params *params); + struct nan_publish_params *params, bool p2p); void hostapd_nan_usd_cancel_publish(struct hostapd_data *hapd, int publish_id); int hostapd_nan_usd_update_publish(struct hostapd_data *hapd, int publish_id, const struct wpabuf *ssi); @@ -29,7 +29,7 @@ int hostapd_nan_usd_subscribe(struct hostapd_data *hapd, const char *service_name, enum nan_service_protocol_type srv_proto_type, const struct wpabuf *ssi, - struct nan_subscribe_params *params); + struct nan_subscribe_params *params, bool p2p); void hostapd_nan_usd_cancel_subscribe(struct hostapd_data *hapd, int subscribe_id); int hostapd_nan_usd_transmit(struct hostapd_data *hapd, int handle, diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index 0fe631026..578ea73a1 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -1425,6 +1425,7 @@ struct ieee80211_ampe_ie { #define WPS_IE_VENDOR_TYPE 0x0050f204 #define OUI_WFA 0x506f9a #define P2P_IE_VENDOR_TYPE 0x506f9a09 +#define P2P2_IE_VENDOR_TYPE 0x506f9a28 #define WFD_IE_VENDOR_TYPE 0x506f9a0a #define WFD_OUI_TYPE 10 #define HS20_IE_VENDOR_TYPE 0x506f9a10 @@ -1740,6 +1741,12 @@ enum p2p_attr_id { P2P_ATTR_SESSION_ID = 26, P2P_ATTR_FEATURE_CAPABILITY = 27, P2P_ATTR_PERSISTENT_GROUP = 28, + P2P_ATTR_CAPABILITY_EXTENSION = 29, + P2P_ATTR_DEVICE_IDENTITY_KEY = 31, + P2P_ATTR_DEVICE_IDENTITY_RESOLUTION = 32, + P2P_ATTR_PAIRING_AND_BOOTSTRAPPING = 33, + P2P_ATTR_PASSWORD = 34, + P2P_ATTR_ACTION_FRAME_WRAPPER = 35, P2P_ATTR_VENDOR_SPECIFIC = 221 }; @@ -1764,6 +1771,18 @@ enum p2p_attr_id { #define P2P_GROUP_CAPAB_GROUP_FORMATION BIT(6) #define P2P_GROUP_CAPAB_IP_ADDR_ALLOCATION BIT(7) +/* P2P Capability Extension attribute - Capability info */ +#define P2P_PCEA_LEN_MASK (BIT(0) | BIT(1) | BIT(2) | BIT(3)) +#define P2P_PCEA_6GHZ BIT(4) +#define P2P_PCEA_REG_INFO BIT(5) +#define P2P_PCEA_DFS_OWNER BIT(6) +#define P2P_PCEA_CLI_REQ_CS BIT(7) +#define P2P_PCEA_PAIRING_CAPABLE BIT(8) +#define P2P_PCEA_PAIRING_SETUP_ENABLE BIT(9) +#define P2P_PCEA_PMK_CACHING BIT(10) +#define P2P_PCEA_PASN_TYPE BIT(11) +#define P2P_PCEA_TWT_POWER_MGMT BIT(12) + /* P2PS Coordination Protocol Transport Bitmap */ #define P2PS_FEATURE_CAPAB_UDP_TRANSPORT BIT(0) #define P2PS_FEATURE_CAPAB_MAC_TRANSPORT BIT(1) diff --git a/src/common/nan_de.c b/src/common/nan_de.c index ecc73c5fd..7017311b6 100644 --- a/src/common/nan_de.c +++ b/src/common/nan_de.c @@ -58,6 +58,7 @@ struct nan_de_service { struct os_reltime next_publish_state; struct os_reltime next_publish_chan; unsigned int next_publish_duration; + bool is_p2p; }; struct nan_de { @@ -1215,7 +1216,7 @@ const u8 * nan_de_get_service_id(struct nan_de *de, int id) int nan_de_publish(struct nan_de *de, const char *service_name, enum nan_service_protocol_type srv_proto_type, const struct wpabuf *ssi, const struct wpabuf *elems, - struct nan_publish_params *params) + struct nan_publish_params *params, bool p2p) { int publish_id; struct nan_de_service *srv; @@ -1271,6 +1272,7 @@ int nan_de_publish(struct nan_de *de, const char *service_name, wpa_printf(MSG_DEBUG, "NAN: Assigned new publish handle %d for %s", publish_id, service_name); srv->id = publish_id; + srv->is_p2p = p2p; nan_de_add_srv(de, srv); nan_de_run_timer(de); return publish_id; @@ -1322,7 +1324,7 @@ int nan_de_update_publish(struct nan_de *de, int publish_id, int nan_de_subscribe(struct nan_de *de, const char *service_name, enum nan_service_protocol_type srv_proto_type, const struct wpabuf *ssi, const struct wpabuf *elems, - struct nan_subscribe_params *params) + struct nan_subscribe_params *params, bool p2p) { int subscribe_id; struct nan_de_service *srv; @@ -1362,6 +1364,7 @@ int nan_de_subscribe(struct nan_de *de, const char *service_name, wpa_printf(MSG_DEBUG, "NAN: Assigned new subscribe handle %d for %s", subscribe_id, service_name); srv->id = subscribe_id; + srv->is_p2p = p2p; nan_de_add_srv(de, srv); nan_de_run_timer(de); return subscribe_id; diff --git a/src/common/nan_de.h b/src/common/nan_de.h index ae77cf399..bdac284b4 100644 --- a/src/common/nan_de.h +++ b/src/common/nan_de.h @@ -106,7 +106,7 @@ struct nan_publish_params { int nan_de_publish(struct nan_de *de, const char *service_name, enum nan_service_protocol_type srv_proto_type, const struct wpabuf *ssi, const struct wpabuf *elems, - struct nan_publish_params *params); + struct nan_publish_params *params, bool p2p); void nan_de_cancel_publish(struct nan_de *de, int publish_id); @@ -133,7 +133,7 @@ struct nan_subscribe_params { int nan_de_subscribe(struct nan_de *de, const char *service_name, enum nan_service_protocol_type srv_proto_type, const struct wpabuf *ssi, const struct wpabuf *elems, - struct nan_subscribe_params *params); + struct nan_subscribe_params *params, bool p2p); void nan_de_cancel_subscribe(struct nan_de *de, int subscribe_id); diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index 8e0fc35df..a2d09624d 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -16,6 +16,7 @@ #include "common/wpa_ctrl.h" #include "crypto/sha256.h" #include "crypto/crypto.h" +#include "crypto/random.h" #include "wps/wps_i.h" #include "p2p_i.h" #include "p2p.h" @@ -2967,6 +2968,37 @@ bool is_p2p_6ghz_disabled(struct p2p_data *p2p) return false; } +int p2p_pairing_info_init(struct p2p_data *p2p) +{ + struct p2p_pairing_info *pairing_info; + + if (!p2p) { + p2p_dbg(p2p, "P2P data NULL"); + return -1; + } + + pairing_info = os_zalloc(sizeof(struct p2p_pairing_info)); + if (!pairing_info) + return -1; + + pairing_info->enable_pairing_setup = + p2p->cfg->pairing_config.enable_pairing_setup; + pairing_info->enable_pairing_cache = + p2p->cfg->pairing_config.enable_pairing_cache; + pairing_info->supported_bootstrap = + p2p->cfg->pairing_config.bootstrap_methods; + + /* TODO: Add support to fetch DIK from p2p_supplicant.conf + * DIK should be same across device reboots + */ + pairing_info->dev_ik.cipher_version = DIRA_CIPHER_VERSION_128; + pairing_info->dev_ik.dik_len = DEVICE_IDENTITY_KEY_LEN; + random_get_bytes(pairing_info->dev_ik.dik_data, + pairing_info->dev_ik.dik_len); + p2p->pairing_info = pairing_info; + + return 0; +} struct p2p_data * p2p_init(const struct p2p_config *cfg) { @@ -3023,6 +3055,7 @@ struct p2p_data * p2p_init(const struct p2p_config *cfg) p2p->go_timeout = 100; p2p->client_timeout = 20; p2p->num_p2p_sd_queries = 0; + p2p_pairing_info_init(p2p); p2p_dbg(p2p, "initialized"); p2p_channels_dump(p2p, "channels", &p2p->cfg->channels); @@ -3031,6 +3064,10 @@ struct p2p_data * p2p_init(const struct p2p_config *cfg) return p2p; } +void p2p_pairing_info_deinit(struct p2p_data *p2p) +{ + os_free(p2p->pairing_info); +} void p2p_deinit(struct p2p_data *p2p) { @@ -3066,6 +3103,7 @@ void p2p_deinit(struct p2p_data *p2p) p2p_remove_wps_vendor_extensions(p2p); os_free(p2p->no_go_freq.range); p2p_service_flush_asp(p2p); + p2p_pairing_info_deinit(p2p); os_free(p2p); } @@ -5688,3 +5726,52 @@ void set_p2p_allow_6ghz(struct p2p_data *p2p, bool value) { p2p->allow_6ghz = value; } + + +struct wpabuf * p2p_usd_elems(struct p2p_data *p2p) +{ + struct wpabuf *buf; + u8 *len; + u8 group_capab; + + buf = wpabuf_alloc(1000); + if (!buf) + return NULL; + + len = p2p_buf_add_ie_hdr(buf); + + /* P2P Capability attribute */ + group_capab = 0; + if (p2p->num_groups) { + group_capab |= P2P_GROUP_CAPAB_GROUP_OWNER; + if ((p2p->dev_capab & P2P_DEV_CAPAB_CONCURRENT_OPER) && + (p2p->dev_capab & P2P_DEV_CAPAB_INFRA_MANAGED) && + p2p->cross_connect) + group_capab |= P2P_GROUP_CAPAB_CROSS_CONN; + } + if (p2p->cfg->p2p_intra_bss) + group_capab |= P2P_GROUP_CAPAB_INTRA_BSS_DIST; + p2p_buf_add_capability(buf, p2p->dev_capab & + ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY, + group_capab); + + /* P2P Device Info attribute */ + p2p_buf_add_device_info(buf, p2p, NULL); + + p2p_buf_update_ie_hdr(buf, len); + + len = p2p_buf_add_p2p2_ie_hdr(buf); + /* P2P Capability Extension attribute */ + p2p_buf_add_pcea(buf, p2p); + + /* P2P Pairing Bootstrapping Method attribute */ + p2p_buf_add_pbma(buf, p2p->cfg->pairing_config.bootstrap_methods, NULL, + 0, 0); + + /* P2P Device Identity Resolution attribute */ + p2p_buf_add_dira(buf, p2p); + + p2p_buf_update_p2p2_ie_hdr(buf, len); + + return buf; +} diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index 27bdac3bf..67124e3c9 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -320,6 +320,42 @@ enum p2p_scan_type { #define P2P_MAX_WPS_VENDOR_EXT 10 +/** + * struct p2p_pairing_config - P2P pairing config. + */ +struct p2p_pairing_config { + /** + * Pairing capable + */ + u8 pairing_capable; + + /** + * Enable P2P pairing setup + */ + u32 enable_pairing_setup; + + /** + * Enable pairing cache to allow verification + */ + u32 enable_pairing_cache; + + /** + * Enable P2P pairing verification with cached NIK/NPK + */ + u32 enable_pairing_verification; + + /** + * P2P bootstrapping methods supported + */ + u16 bootstrap_methods; + + /** + * The set of supported PASN type + */ + u8 pasn_type; +}; + + /** * struct p2p_peer_info - P2P peer information */ @@ -589,6 +625,31 @@ struct p2p_config { */ unsigned int passphrase_len; + /** + * p2p_pairing_config - P2P Pairing configuration + */ + struct p2p_pairing_config pairing_config; + + /** + * p2p_6ghz_enable - 6GHz enable for P2P operations + */ + bool p2p_6ghz_enable; + + /** + * reg_info - regulatory info encoding for operation in 6 GHz band + */ + u8 reg_info; + + /** + * dfs_owner - Enable p2p GO to act as DFS Owner + */ + bool dfs_owner; + + /** + * twt_power_mgmt - Enable TWT based power mgmt for P2P + */ + bool twt_power_mgmt; + /** * cb_ctx - Context to use with callback functions */ @@ -2429,5 +2490,6 @@ bool is_p2p_allow_6ghz(struct p2p_data *p2p); void set_p2p_allow_6ghz(struct p2p_data *p2p, bool value); int p2p_remove_6ghz_channels(struct weighted_pcl *pref_freq_list, int size); int p2p_channel_to_freq(int op_class, int channel); +struct wpabuf * p2p_usd_elems(struct p2p_data *p2p); #endif /* P2P_H */ diff --git a/src/p2p/p2p_build.c b/src/p2p/p2p_build.c index e4f40fe8f..641f9dd47 100644 --- a/src/p2p/p2p_build.c +++ b/src/p2p/p2p_build.c @@ -12,10 +12,11 @@ #include "common/ieee802_11_defs.h" #include "common/ieee802_11_common.h" #include "common/qca-vendor.h" +#include "crypto/random.h" +#include "crypto/sha256.h" #include "wps/wps_i.h" #include "p2p_i.h" - void p2p_buf_add_action_hdr(struct wpabuf *buf, u8 subtype, u8 dialog_token) { wpabuf_put_u8(buf, WLAN_ACTION_VENDOR_SPECIFIC); @@ -59,6 +60,24 @@ void p2p_buf_update_ie_hdr(struct wpabuf *buf, u8 *len) *len = (u8 *) wpabuf_put(buf, 0) - len - 1; } +u8 * p2p_buf_add_p2p2_ie_hdr(struct wpabuf *buf) +{ + u8 *len; + + /* P2P2 IE header */ + wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC); + len = wpabuf_put(buf, 1); /* IE length to be filled */ + wpabuf_put_be32(buf, P2P2_IE_VENDOR_TYPE); + wpa_printf(MSG_DEBUG, "P2P: * P2P2 IE header"); + return len; +} + + +void p2p_buf_update_p2p2_ie_hdr(struct wpabuf *buf, u8 *len) +{ + /* Update P2P2 IE Length */ + *len = (u8 *) wpabuf_put(buf, 0) - len - 1; +} void p2p_buf_add_capability(struct wpabuf *buf, u8 dev_capab, u8 group_capab) { @@ -709,6 +728,167 @@ void p2p_buf_add_persistent_group_info(struct wpabuf *buf, const u8 *dev_addr, } +void p2p_buf_add_pcea(struct wpabuf *buf, struct p2p_data *p2p) +{ + u8 *len; + u16 capability_info = 0; + + /* P2P Capability Extension */ + wpabuf_put_u8(buf, P2P_ATTR_CAPABILITY_EXTENSION); + /* Length to be filled */ + len = wpabuf_put(buf, 2); + + if (p2p->cfg->p2p_6ghz_enable) + capability_info |= P2P_PCEA_6GHZ; + + if (p2p->cfg->reg_info) + capability_info |= P2P_PCEA_REG_INFO; + + if (p2p->cfg->dfs_owner) + capability_info |= P2P_PCEA_DFS_OWNER; + + if (p2p->cfg->pairing_config.pairing_capable) + capability_info |= P2P_PCEA_PAIRING_CAPABLE; + + if (p2p->cfg->pairing_config.enable_pairing_setup) + capability_info |= P2P_PCEA_PAIRING_SETUP_ENABLE; + + if (p2p->cfg->pairing_config.enable_pairing_cache) + capability_info |= P2P_PCEA_PMK_CACHING; + + if (p2p->cfg->pairing_config.pasn_type) + capability_info |= P2P_PCEA_PASN_TYPE; + + if (p2p->cfg->twt_power_mgmt) + capability_info |= P2P_PCEA_TWT_POWER_MGMT; + + /* Field length is (n-1), n in octets */ + capability_info |= (2 - 1) & P2P_PCEA_LEN_MASK; + wpabuf_put_le16(buf, capability_info); + + if (capability_info & P2P_PCEA_REG_INFO) + wpabuf_put_u8(buf, p2p->cfg->reg_info); + + if (capability_info & P2P_PCEA_PASN_TYPE) + wpabuf_put_u8(buf, p2p->cfg->pairing_config.pasn_type); + + /* Update attribute length */ + WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2); + + wpa_printf(MSG_DEBUG, "P2P: * Capability Extension info=0x%x", + capability_info); +} + +void p2p_buf_add_pbma(struct wpabuf *buf, u16 bootstrap, const u8 *cookie, + size_t cookie_len, int comeback_after) +{ + u8 *len; + + if (!bootstrap) + return; + + /* P2P Pairing and Bootstrapping methods */ + wpabuf_put_u8(buf, P2P_ATTR_PAIRING_AND_BOOTSTRAPPING); + /* Length to be filled */ + len = wpabuf_put(buf, 2); + + if (cookie && cookie_len) { + if (comeback_after) + wpabuf_put_le16(buf, comeback_after); + wpabuf_put_u8(buf, cookie_len); + wpabuf_put_data(buf, cookie, cookie_len); + } + wpabuf_put_le16(buf, bootstrap); + + /* Update attribute length */ + WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2); + + wpa_printf(MSG_DEBUG, "P2P: * Bootstrapping method=0x%x", + bootstrap); +} + +static int p2p_derive_nonce_tag(struct p2p_data *p2p) +{ + int ret; + u8 dira_nonce[DEVICE_IDENTITY_NONCE_LEN]; + u8 dira_tag[DEVICE_MAX_HASH_LEN]; + u8 data[DIR_STR_LEN + DEVICE_IDENTITY_NONCE_LEN + ETH_ALEN]; + struct p2p_id_key *dev_ik; + + dev_ik = &p2p->pairing_info->dev_ik; + + if (dev_ik->cipher_version != DIRA_CIPHER_VERSION_128) { + wpa_printf(MSG_ERROR, "Unsupported DIRA Cipher version = %d", + dev_ik->cipher_version); + return -1; + } + + if (dev_ik->dik_len != DEVICE_IDENTITY_KEY_LEN) { + wpa_printf(MSG_ERROR, "Invalid DIK length = %ld", + dev_ik->dik_len); + return -1; + } + + if (dev_ik->dira_nonce_len && dev_ik->dira_tag_len) + return 0; + + os_memset(data, 0, sizeof(data)); + os_memset(dira_tag, 0, sizeof(dira_tag)); + + ret = random_get_bytes(dira_nonce, DEVICE_IDENTITY_NONCE_LEN); + if (ret < 0) { + wpa_printf(MSG_ERROR, "Get DIRA nonce Failed, err = %d", ret); + return -1; + } + + os_memcpy(data, "DIR", DIR_STR_LEN); + os_memcpy(&data[DIR_STR_LEN], p2p->cfg->dev_addr, ETH_ALEN); + os_memcpy(&data[DIR_STR_LEN + ETH_ALEN], dira_nonce, + DEVICE_IDENTITY_NONCE_LEN); + + ret = hmac_sha256(dev_ik->dik_data, DEVICE_IDENTITY_KEY_LEN, data, + sizeof(data), dira_tag); + if (ret < 0) { + wpa_printf(MSG_ERROR, "Could not derive DIRA tag, err = %d", ret); + return -1; + } + + dev_ik->dira_nonce_len = DEVICE_IDENTITY_NONCE_LEN; + os_memcpy(dev_ik->dira_nonce, dira_nonce, DEVICE_IDENTITY_NONCE_LEN); + dev_ik->dira_tag_len = DEVICE_IDENTITY_TAG_LEN; + os_memcpy(dev_ik->dira_tag, dira_tag, DEVICE_IDENTITY_TAG_LEN); + return 0; +} + +void p2p_buf_add_dira(struct wpabuf *buf, struct p2p_data *p2p) +{ + u8 *len; + struct p2p_id_key *dev_ik; + + if (!p2p->cfg->pairing_config.pairing_capable || + !p2p->cfg->pairing_config.enable_pairing_cache || + !p2p->cfg->pairing_config.enable_pairing_verification) + return; + + if (p2p_derive_nonce_tag(p2p)) + return; + + dev_ik = &p2p->pairing_info->dev_ik; + /* P2P DIRA */ + wpabuf_put_u8(buf, P2P_ATTR_DEVICE_IDENTITY_RESOLUTION); + /* Length to be filled */ + len = wpabuf_put(buf, 2); + + wpabuf_put_u8(buf, dev_ik->cipher_version); + wpabuf_put_data(buf, dev_ik->dira_nonce, dev_ik->dira_nonce_len); + wpabuf_put_data(buf, dev_ik->dira_tag, dev_ik->dira_tag_len); + + /* Update attribute length */ + WPA_PUT_LE16(len, (u8 *)wpabuf_put(buf, 0) - len - 2); + + wpa_printf(MSG_DEBUG, "P2P: * Added DIRA"); +} + static int p2p_add_wps_string(struct wpabuf *buf, enum wps_attribute attr, const char *val) { diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h index 0a487e031..0e24e51ab 100644 --- a/src/p2p/p2p_i.h +++ b/src/p2p/p2p_i.h @@ -14,6 +14,11 @@ #include "p2p.h" #define P2P_GO_NEG_CNF_MAX_RETRY_COUNT 1 +#define DEVICE_IDENTITY_KEY_LEN 16 +#define DEVICE_IDENTITY_TAG_LEN 8 +#define DEVICE_IDENTITY_NONCE_LEN 8 +#define DEVICE_MAX_HASH_LEN 32 +#define DIR_STR_LEN 3 /* * A threshold (in seconds) to prefer a direct Probe Response frame from a P2P @@ -160,6 +165,44 @@ struct p2p_sd_query { struct wpabuf *tlvs; }; +/* DIRA Cipher versions */ +#define DIRA_CIPHER_VERSION_128 0 + +/* This is p2p device identity key params */ +struct p2p_id_key { + /* AKMP used for DevIK derviation */ + int akmp; + /* cipher version type */ + int cipher_version; + /* DevIK expiration time in seconds */ + u32 expiration; + /* buffer to hold the DevIK */ + u8 dik_data[DEVICE_IDENTITY_KEY_LEN]; + /* length of DevIK */ + size_t dik_len; + /* nonce used in DIRA attribute */ + u8 dira_nonce[DEVICE_IDENTITY_NONCE_LEN]; + /* length of nonce */ + size_t dira_nonce_len; + /* tag computed for nonce using NIK */ + u8 dira_tag[DEVICE_IDENTITY_TAG_LEN]; + /* length of tag */ + size_t dira_tag_len; +}; + +struct p2p_pairing_info { + /* P2P device own address */ + u8 own_addr[ETH_ALEN]; + /* device capability to enable pairing setup */ + u32 enable_pairing_setup; + /* device capability to enable pairing cache */ + u32 enable_pairing_cache; + /* device supported bootstrapping */ + u16 supported_bootstrap; + /* p2p device identity key info */ + struct p2p_id_key dev_ik; +}; + /** * struct p2p_data - P2P module data (internal to P2P module) */ @@ -554,6 +597,8 @@ struct p2p_data { bool p2p_6ghz_capable; bool include_6ghz; bool allow_6ghz; + + struct p2p_pairing_info *pairing_info; }; /** @@ -748,11 +793,13 @@ void p2p_buf_add_action_hdr(struct wpabuf *buf, u8 subtype, u8 dialog_token); void p2p_buf_add_public_action_hdr(struct wpabuf *buf, u8 subtype, u8 dialog_token); u8 * p2p_buf_add_ie_hdr(struct wpabuf *buf); +u8 * p2p_buf_add_p2p2_ie_hdr(struct wpabuf *buf); void p2p_buf_add_status(struct wpabuf *buf, u8 status); void p2p_buf_add_device_info(struct wpabuf *buf, struct p2p_data *p2p, struct p2p_device *peer); void p2p_buf_add_device_id(struct wpabuf *buf, const u8 *dev_addr); void p2p_buf_update_ie_hdr(struct wpabuf *buf, u8 *len); +void p2p_buf_update_p2p2_ie_hdr(struct wpabuf *buf, u8 *len); void p2p_buf_add_capability(struct wpabuf *buf, u8 dev_capab, u8 group_capab); void p2p_buf_add_go_intent(struct wpabuf *buf, u8 go_intent); void p2p_buf_add_listen_channel(struct wpabuf *buf, const char *country, @@ -788,6 +835,10 @@ void p2p_buf_add_feature_capability(struct wpabuf *buf, u16 len, const u8 *mask); void p2p_buf_add_persistent_group_info(struct wpabuf *buf, const u8 *dev_addr, const u8 *ssid, size_t ssid_len); +void p2p_buf_add_pcea(struct wpabuf *buf, struct p2p_data *p2p); +void p2p_buf_add_pbma(struct wpabuf *buf, u16 bootstrap, const u8 *cookie, + size_t cookie_len, int comeback_after); +void p2p_buf_add_dira(struct wpabuf *buf, struct p2p_data *p2p); int p2p_build_wps_ie(struct p2p_data *p2p, struct wpabuf *buf, int pw_id, int all_attr); void p2p_buf_add_pref_channel_list(struct wpabuf *buf, diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 74d61132e..03434c5ef 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -12193,6 +12193,7 @@ static int wpas_ctrl_nan_publish(struct wpa_supplicant *wpa_s, char *cmd, int ret = -1; enum nan_service_protocol_type srv_proto_type = 0; int *freq_list = NULL; + bool p2p = false; os_memset(¶ms, 0, sizeof(params)); /* USD shall use both solicited and unsolicited transmissions */ @@ -12253,6 +12254,11 @@ static int wpas_ctrl_nan_publish(struct wpa_supplicant *wpa_s, char *cmd, continue; } + if (os_strcmp(token, "p2p=1") == 0) { + p2p = true; + continue; + } + if (os_strcmp(token, "solicited=0") == 0) { params.solicited = false; continue; @@ -12274,7 +12280,7 @@ static int wpas_ctrl_nan_publish(struct wpa_supplicant *wpa_s, char *cmd, } publish_id = wpas_nan_usd_publish(wpa_s, service_name, srv_proto_type, - ssi, ¶ms); + ssi, ¶ms, p2p); if (publish_id > 0) ret = os_snprintf(buf, buflen, "%d", publish_id); fail: @@ -12358,6 +12364,7 @@ static int wpas_ctrl_nan_subscribe(struct wpa_supplicant *wpa_s, char *cmd, struct wpabuf *ssi = NULL; int ret = -1; enum nan_service_protocol_type srv_proto_type = 0; + bool p2p = false; os_memset(¶ms, 0, sizeof(params)); params.freq = NAN_USD_DEFAULT_FREQ; @@ -12397,6 +12404,11 @@ static int wpas_ctrl_nan_subscribe(struct wpa_supplicant *wpa_s, char *cmd, continue; } + if (os_strcmp(token, "p2p=1") == 0) { + p2p = true; + continue; + } + wpa_printf(MSG_INFO, "CTRL: Invalid NAN_SUBSCRIBE parameter: %s", token); @@ -12405,7 +12417,7 @@ static int wpas_ctrl_nan_subscribe(struct wpa_supplicant *wpa_s, char *cmd, subscribe_id = wpas_nan_usd_subscribe(wpa_s, service_name, srv_proto_type, ssi, - ¶ms); + ¶ms, p2p); if (subscribe_id > 0) ret = os_snprintf(buf, buflen, "%d", subscribe_id); fail: diff --git a/wpa_supplicant/nan_usd.c b/wpa_supplicant/nan_usd.c index 3fea540b9..0b329499f 100644 --- a/wpa_supplicant/nan_usd.c +++ b/wpa_supplicant/nan_usd.c @@ -13,6 +13,7 @@ #include "wpa_supplicant_i.h" #include "offchannel.h" #include "driver_i.h" +#include "p2p_supplicant.h" #include "nan_usd.h" @@ -386,7 +387,7 @@ void wpas_nan_usd_flush(struct wpa_supplicant *wpa_s) int wpas_nan_usd_publish(struct wpa_supplicant *wpa_s, const char *service_name, enum nan_service_protocol_type srv_proto_type, const struct wpabuf *ssi, - struct nan_publish_params *params) + struct nan_publish_params *params, bool p2p) { int publish_id; struct wpabuf *elems = NULL; @@ -394,8 +395,11 @@ int wpas_nan_usd_publish(struct wpa_supplicant *wpa_s, const char *service_name, if (!wpa_s->nan_de) return -1; + if (p2p) + elems = wpas_p2p_usd_elems(wpa_s); + publish_id = nan_de_publish(wpa_s->nan_de, service_name, srv_proto_type, - ssi, elems, params); + ssi, elems, params, p2p); if (publish_id <= 0) goto fail; if ((wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_NAN_OFFLOAD) && @@ -443,7 +447,7 @@ int wpas_nan_usd_subscribe(struct wpa_supplicant *wpa_s, const char *service_name, enum nan_service_protocol_type srv_proto_type, const struct wpabuf *ssi, - struct nan_subscribe_params *params) + struct nan_subscribe_params *params, bool p2p) { int subscribe_id; struct wpabuf *elems = NULL; @@ -451,8 +455,12 @@ int wpas_nan_usd_subscribe(struct wpa_supplicant *wpa_s, if (!wpa_s->nan_de) return -1; + if (p2p) + elems = wpas_p2p_usd_elems(wpa_s); + subscribe_id = nan_de_subscribe(wpa_s->nan_de, service_name, - srv_proto_type, ssi, elems, params); + srv_proto_type, ssi, elems, params, + p2p); if (subscribe_id <= 0) goto fail; if ((wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_NAN_OFFLOAD) && diff --git a/wpa_supplicant/nan_usd.h b/wpa_supplicant/nan_usd.h index 149ac9e60..ecb4973c4 100644 --- a/wpa_supplicant/nan_usd.h +++ b/wpa_supplicant/nan_usd.h @@ -21,7 +21,7 @@ void wpas_nan_usd_flush(struct wpa_supplicant *wpa_s); int wpas_nan_usd_publish(struct wpa_supplicant *wpa_s, const char *service_name, enum nan_service_protocol_type srv_proto_type, const struct wpabuf *ssi, - struct nan_publish_params *params); + struct nan_publish_params *params, bool p2p); void wpas_nan_usd_cancel_publish(struct wpa_supplicant *wpa_s, int publish_id); int wpas_nan_usd_update_publish(struct wpa_supplicant *wpa_s, int publish_id, const struct wpabuf *ssi); @@ -29,7 +29,7 @@ int wpas_nan_usd_subscribe(struct wpa_supplicant *wpa_s, const char *service_name, enum nan_service_protocol_type srv_proto_type, const struct wpabuf *ssi, - struct nan_subscribe_params *params); + struct nan_subscribe_params *params, bool p2p); void wpas_nan_usd_cancel_subscribe(struct wpa_supplicant *wpa_s, int subscribe_id); int wpas_nan_usd_transmit(struct wpa_supplicant *wpa_s, int handle, diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 70025f1e4..2df2d108b 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -10242,3 +10242,13 @@ int wpas_p2p_lo_stop(struct wpa_supplicant *wpa_s) wpa_s->p2p_lo_started = 0; return ret; } + + +struct wpabuf * wpas_p2p_usd_elems(struct wpa_supplicant *wpa_s) +{ + struct p2p_data *p2p = wpa_s->global->p2p; + + if (wpa_s->global->p2p_disabled || !p2p) + return NULL; + return p2p_usd_elems(p2p); +} diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h index d71f7701c..441e063d9 100644 --- a/wpa_supplicant/p2p_supplicant.h +++ b/wpa_supplicant/p2p_supplicant.h @@ -225,6 +225,7 @@ int wpas_p2p_lo_start(struct wpa_supplicant *wpa_s, unsigned int freq, unsigned int count); int wpas_p2p_lo_stop(struct wpa_supplicant *wpa_s); int wpas_p2p_mac_setup(struct wpa_supplicant *wpa_s); +struct wpabuf * wpas_p2p_usd_elems(struct wpa_supplicant *wpa_s); #else /* CONFIG_P2P */ @@ -351,6 +352,11 @@ static inline int wpas_p2p_group_remove(struct wpa_supplicant *wpa_s, return 0; } +static inline struct wpabuf * wpas_p2p_usd_elems(struct wpa_supplicant *wpa_s) +{ + return NULL; +} + #endif /* CONFIG_P2P */ #endif /* P2P_SUPPLICANT_H */ -- 2.34.1 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap