From 5b0112a1855203e53e38afb6865d4dea9d5db740 Mon Sep 17 00:00:00 2001 From: Shivani Baranwal Date: Mon, 5 Aug 2024 15:03:02 +0530 Subject: [PATCH] P2P2: Add DIRA attributes to P2P2 IE of NAN SDFs Add DIRA attribute in P2P2 IE of NAN Subscribe and Publish frames to enable support for device identity of paired peers. Signed-off-by: Shivani Baranwal --- src/p2p/p2p.c | 76 +++++++++++++++++++++++++++++++++++++++++++++ src/p2p/p2p.h | 19 ++++++++++++ src/p2p/p2p_build.c | 27 ++++++++++++++++ src/p2p/p2p_i.h | 23 ++++++++++++++ 4 files changed, 145 insertions(+) diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index eee6f8b87..8d8f58e6d 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -2978,6 +2978,9 @@ static int p2p_pairing_info_init(struct p2p_data *p2p) { struct p2p_pairing_info *pairing_info; + if (p2p->cfg->pairing_config.dik_len > DEVICE_IDENTITY_KEY_MAX_LEN) + return -1; + pairing_info = os_zalloc(sizeof(struct p2p_pairing_info)); if (!pairing_info) return -1; @@ -2989,6 +2992,13 @@ static int p2p_pairing_info_init(struct p2p_data *p2p) pairing_info->supported_bootstrap = p2p->cfg->pairing_config.bootstrap_methods; + pairing_info->dev_ik.cipher_version = + p2p->cfg->pairing_config.dik_cipher; + pairing_info->dev_ik.dik_len = p2p->cfg->pairing_config.dik_len; + os_memcpy(pairing_info->dev_ik.dik_data, + p2p->cfg->pairing_config.dik_data, + p2p->cfg->pairing_config.dik_len); + p2p_pairing_info_deinit(p2p); p2p->pairing_info = pairing_info; @@ -5720,6 +5730,64 @@ void set_p2p_allow_6ghz(struct p2p_data *p2p, bool value) } +static int p2p_derive_nonce_tag(struct p2p_data *p2p) +{ + 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_INFO, + "P2P: Unsupported DIRA Cipher version = %d", + dev_ik->cipher_version); + return -1; + } + + if (dev_ik->dik_len != DEVICE_IDENTITY_KEY_LEN) { + wpa_printf(MSG_INFO, "P2P: Invalid DIK length = %zu", + dev_ik->dik_len); + return -1; + } + + os_memset(data, 0, sizeof(data)); + + if (os_get_random(dira_nonce, DEVICE_IDENTITY_NONCE_LEN) < 0) { + wpa_printf(MSG_ERROR, "P2P: Failed to generate DIRA nonce"); + return -1; + } + + /* Tag = Truncate-64(HMAC-SHA-256(DevIK, + * "DIR" || P2P Device Address || Nonce)) + */ + 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); + + if (hmac_sha256(dev_ik->dik_data, dev_ik->dik_len, data, sizeof(data), + dira_tag) < 0) { + wpa_printf(MSG_ERROR, "P2P: Could not derive DIRA tag"); + 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); + + wpa_hexdump_key(MSG_DEBUG, "P2P: DIK", dev_ik->dik_data, + dev_ik->dik_len); + wpa_hexdump_key(MSG_DEBUG, "P2P: DIRA-NONCE", dev_ik->dira_nonce, + dev_ik->dira_nonce_len); + wpa_hexdump_key(MSG_DEBUG, "P2P: DIRA-TAG", dev_ik->dira_tag, + dev_ik->dira_tag_len); + return 0; +} + + struct wpabuf * p2p_usd_elems(struct p2p_data *p2p) { struct wpabuf *buf; @@ -5761,6 +5829,14 @@ struct wpabuf * p2p_usd_elems(struct p2p_data *p2p) p2p_buf_add_pbma(buf, p2p->cfg->pairing_config.bootstrap_methods, NULL, 0, 0); + /* P2P Device Identity Resolution attribute */ + if (p2p->pairing_info && + p2p->cfg->pairing_config.pairing_capable && + p2p->cfg->pairing_config.enable_pairing_cache && + p2p->cfg->pairing_config.enable_pairing_verification && + p2p_derive_nonce_tag(p2p) == 0) + p2p_buf_add_dira(buf, p2p); + p2p_buf_update_ie_hdr(buf, len); return buf; diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index a3aca142b..039c027c6 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -12,6 +12,16 @@ #include "common/ieee802_11_defs.h" #include "wps/wps.h" +#define DEVICE_IDENTITY_KEY_MAX_LEN 64 +#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 + +/* DIRA Cipher versions */ +#define DIRA_CIPHER_VERSION_128 0 + struct weighted_pcl; /* P2P ASP Setup Capability */ @@ -353,6 +363,15 @@ struct p2p_pairing_config { * Bitmap of supported PASN types */ u8 pasn_type; + + /* Cipher version type */ + int dik_cipher; + + /* Buffer to hold the DevIK */ + u8 dik_data[DEVICE_IDENTITY_KEY_MAX_LEN]; + + /* Length of DevIK in octets */ + size_t dik_len; }; /** diff --git a/src/p2p/p2p_build.c b/src/p2p/p2p_build.c index f088c01f0..78ef2dbcd 100644 --- a/src/p2p/p2p_build.c +++ b/src/p2p/p2p_build.c @@ -800,6 +800,33 @@ void p2p_buf_add_pbma(struct wpabuf *buf, u16 bootstrap, const u8 *cookie, } +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; + + 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: * 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 d1bef9101..3da75582f 100644 --- a/src/p2p/p2p_i.h +++ b/src/p2p/p2p_i.h @@ -160,6 +160,26 @@ struct p2p_sd_query { struct wpabuf *tlvs; }; +/* P2P Device Identity Key parameters */ +struct p2p_id_key { + /* AKMP used for DevIK derviation */ + int akmp; + /* Cipher version type */ + int cipher_version; + /* Buffer to hold the DevIK */ + u8 dik_data[DEVICE_IDENTITY_KEY_MAX_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 in octets */ + size_t dira_tag_len; +}; + struct p2p_pairing_info { /* P2P device own address */ u8 own_addr[ETH_ALEN]; @@ -169,6 +189,8 @@ struct p2p_pairing_info { bool enable_pairing_cache; /* device supported bootstrapping */ u16 supported_bootstrap; + /* P2P Device Identity Key info */ + struct p2p_id_key dev_ik; }; /** @@ -805,6 +827,7 @@ 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); 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,