]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
P2P2: Add DIRA attributes to P2P2 IE of NAN SDFs
authorShivani Baranwal <quic_shivbara@quicinc.com>
Mon, 5 Aug 2024 09:33:02 +0000 (15:03 +0530)
committerJouni Malinen <j@w1.fi>
Tue, 27 Aug 2024 07:51:56 +0000 (10:51 +0300)
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 <quic_shivbara@quicinc.com>
src/p2p/p2p.c
src/p2p/p2p.h
src/p2p/p2p_build.c
src/p2p/p2p_i.h

index eee6f8b870b83833c8be3d22b2f2ced1b7b967a4..8d8f58e6dca2cae5553bd1a4f4d805f7d6715d67 100644 (file)
@@ -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;
index a3aca142b46dd68962447daadd91fe0976f7b580..039c027c6804da3510796ce29b8f6f36d4b25521 100644 (file)
 #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;
 };
 
 /**
index f088c01f0b4039d6f8badbfc3694008fc2214761..78ef2dbcd039731175be6d08c35658363b129c04 100644 (file)
@@ -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)
 {
index d1bef9101ddc8c1ba3a3c388de5daf18d168429e..3da75582f9a6ab0b3a517210665326f4f6152c47 100644 (file)
@@ -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,