]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
P2P2: Parser function for PASN Encrypted Data element and DevIK
authorShivani Baranwal <quic_shivbara@quicinc.com>
Sun, 4 Aug 2024 21:13:59 +0000 (02:43 +0530)
committerJouni Malinen <j@w1.fi>
Sun, 13 Oct 2024 18:41:53 +0000 (21:41 +0300)
Parse the encrypted P2P2 IE from PASN authentication frames and store a
copy of DevIK information so that this is available for use if the
connection succeeds for a persistent group.

Signed-off-by: Shivani Baranwal <quic_shivbara@quicinc.com>
src/p2p/p2p.c
src/p2p/p2p.h
src/p2p/p2p_i.h

index e109e320ca8e6e19d0a7a7221a10c7fdd04b9005..0dde48b4218b4dd4a1ce72c35c1755c9849af9b1 100644 (file)
@@ -6419,6 +6419,90 @@ out:
 }
 
 
+int p2p_parse_data_element(struct p2p_data *p2p, const u8 *data, size_t len)
+{
+       u8 attr_id;
+       const u8 *pos, *next;
+       u16 rem_len, attr_len;
+
+       if (!p2p || !data || !len)
+               return -1;
+
+       pos = data;
+       rem_len = len;
+
+       if (rem_len < 6 ||
+           pos[0] != WLAN_EID_VENDOR_SPECIFIC ||
+           pos[1] < 4 ||
+           rem_len < 2 + pos[1] ||
+           WPA_GET_BE32(&pos[2]) != P2P2_IE_VENDOR_TYPE) {
+               p2p_dbg(p2p,
+                       "P2P: P2P2 IE not present in PASN Encrypted Data element");
+               return -1;
+       }
+
+       pos += 6;
+       rem_len -= 6;
+
+       while (rem_len >= 3) {
+               attr_id = *pos++;
+               attr_len = WPA_GET_LE16(pos);
+               pos += 2;
+               rem_len -= 3;
+               if (rem_len < attr_len)
+                       return -1;
+               next = pos + attr_len;
+               rem_len -= attr_len;
+
+               switch (attr_id) {
+               case P2P_ATTR_DEVICE_IDENTITY_KEY:
+                       if (attr_len < 1) {
+                               p2p_dbg(p2p,
+                                       "Too short Device Identity Key attribute");
+                               return -1;
+                       }
+                       p2p->dik_cipher_version = *pos++;
+                       attr_len--;
+                       if (p2p->dik_cipher_version ==
+                           DIRA_CIPHER_VERSION_128) {
+                               if (attr_len < DEVICE_IDENTITY_KEY_LEN) {
+                                       p2p_dbg(p2p, "Too short DevIK");
+                                       return -1;
+                               }
+                               os_memcpy(p2p->peer_dik_data, pos,
+                                         DEVICE_IDENTITY_KEY_LEN);
+                               p2p->peer_dik_len = DEVICE_IDENTITY_KEY_LEN;
+                               pos += DEVICE_IDENTITY_KEY_LEN;
+                               attr_len -= DEVICE_IDENTITY_KEY_LEN;
+                       } else {
+                               p2p_dbg(p2p,
+                                       "Unsupported cipher version %u in Device Identity Key attribute",
+                                       p2p->dik_cipher_version);
+                               return -1;
+                       }
+                       if (attr_len < 4) {
+                               p2p_dbg(p2p,
+                                       "Not enough room for DevIK lifetime");
+                               return -1;
+                       }
+                       p2p->peer_dik_lifetime = WPA_GET_BE32(pos);
+                       p2p_dbg(p2p,
+                               "Received peer DevIK of length %zu octets and lifetime %u",
+                               p2p->peer_dik_len, p2p->peer_dik_lifetime);
+                       break;
+               default:
+                       p2p_dbg(p2p,
+                               "Unsupported Attribute ID %u in P2P2 IE in PASN Encrypted Data element",
+                               attr_id);
+                       break;
+               }
+               pos = next;
+       }
+
+       return 0;
+}
+
+
 int p2p_pasn_auth_tx_status(struct p2p_data *p2p, const u8 *data,
                            size_t data_len, bool acked)
 {
@@ -6533,6 +6617,9 @@ static int p2p_handle_pasn_auth(struct p2p_data *p2p, struct p2p_device *dev,
                                                   auth_transaction)) {
                        p2p_dbg(p2p,
                                "PASN Responder: Handle Auth 3 action wrapper failed");
+                       /* Drop keying material from a failed pairing attempt */
+                       os_memset(p2p->peer_dik_data, 0,
+                                 sizeof(p2p->peer_dik_data));
                        return -1;
                }
                forced_memzero(pasn_get_ptk(pasn), sizeof(pasn->ptk));
index 56b80d89eb484b15ad30611ead4a77df687d3f8b..ab93900e46a7e497a8301138755aaa78647bcb27 100644 (file)
@@ -2580,6 +2580,7 @@ int p2p_initiate_pasn_auth(struct p2p_data *p2p, const u8 *addr, int freq);
 int p2p_pasn_auth_rx(struct p2p_data *p2p, const struct ieee80211_mgmt *mgmt,
                     size_t len, int freq);
 int p2p_prepare_data_element(struct p2p_data *p2p, const u8 *peer_addr);
+int p2p_parse_data_element(struct p2p_data *p2p, const u8 *data, size_t len);
 int p2p_pasn_auth_tx_status(struct p2p_data *p2p, const u8 *data,
                            size_t data_len, bool acked);
 
index d7dfba8254a6b7b0c10c6471a767df88db4058d7..571f4fc93342c0194f9d81dbab27b00602dd7f8c 100644 (file)
@@ -642,6 +642,19 @@ struct p2p_data {
        struct rsn_pmksa_cache *initiator_pmksa;
        /* Pairing responder PMKSA cache */
        struct rsn_pmksa_cache *responder_pmksa;
+
+       /* DevIK variables: Cipher version, DevIK, and its lifetime
+        * These are fetched from the P2P2 included in the PASN Encrypted Data
+        * element during P2P2 group negotiation with PASN Authentication
+        * frames. These values are stored in struct p2p_data for an ongoing GO
+        * negotiation or join-a-group operation with the assumption that these
+        * operations cannot happen in parallel with multiple peers. After
+        * successful group formation and connection, these are moved to
+        * wpa_supplicant configuration if the connection is persistent. */
+       u8 dik_cipher_version;
+       u8 peer_dik_data[DEVICE_IDENTITY_KEY_MAX_LEN];
+       size_t peer_dik_len;
+       unsigned int peer_dik_lifetime;
 };
 
 /**