]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
PASN: Routines for generating and processing encrypted data
authorShivani Baranwal <quic_shivbara@quicinc.com>
Sun, 4 Aug 2024 21:13:59 +0000 (02:43 +0530)
committerJouni Malinen <j@w1.fi>
Fri, 27 Sep 2024 09:44:30 +0000 (12:44 +0300)
This adds functions to use the PASN Encrypted Data element based on the
definition in IEEE P802.11bh/D6.0.

Signed-off-by: Shivani Baranwal <quic_shivbara@quicinc.com>
src/pasn/pasn_common.c
src/pasn/pasn_common.h
src/pasn/pasn_initiator.c
src/pasn/pasn_responder.c

index 25e44a1953d4f5a5c101dd61552e86ab9a49620d..b5dd1758df37ae5fafd1b10ffe981f6660bbd582 100644 (file)
@@ -15,6 +15,8 @@
 #include "crypto/sha384.h"
 #include "crypto/crypto.h"
 #include "common/ieee802_11_defs.h"
+#include "common/ieee802_11_common.h"
+#include "crypto/aes_wrap.h"
 #include "pasn_common.h"
 
 
@@ -241,3 +243,102 @@ struct wpa_ptk * pasn_get_ptk(struct pasn_data *pasn)
                return NULL;
        return &pasn->ptk;
 }
+
+
+int pasn_add_encrypted_data(struct pasn_data *pasn, struct wpabuf *buf,
+                           const u8 *data, size_t data_len)
+{
+       int ret;
+       u8 *encrypted_data, *padded_data = NULL;
+       u8 *len;
+       size_t pad_len = 0;
+
+       pad_len = data_len % 8;
+       if (pad_len) {
+               pad_len = 8 - pad_len;
+               padded_data = os_zalloc(data_len + pad_len);
+               if (!padded_data)
+                       return -1;
+               os_memcpy(padded_data, data, data_len);
+               data = padded_data;
+               padded_data[data_len] = 0xdd;
+       }
+       data_len += pad_len + 8;
+
+       encrypted_data = os_malloc(data_len);
+       if (!encrypted_data) {
+               os_free(padded_data);
+               return -1;
+       }
+
+       ret = aes_wrap(pasn->ptk.kek, pasn->ptk.kek_len,
+                      (data_len - 8) / 8, data, encrypted_data);
+       if (ret) {
+               wpa_printf(MSG_DEBUG, "PASN: AES wrap failed, ret=%d", ret);
+               goto out;
+       }
+
+       if (wpabuf_tailroom(buf) < 1 + 1 + 1 + data_len) {
+               wpa_printf(MSG_DEBUG,
+                          "PASN: Not enough room in the buffer for PASN Encrypred Data element");
+               ret = -1;
+               goto out;
+       }
+
+       wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
+       len = wpabuf_put(buf, 1);
+
+       wpabuf_put_u8(buf, WLAN_EID_EXT_PASN_ENCRYPTED_DATA);
+
+       wpabuf_put_data(buf, encrypted_data, data_len);
+       *len = (u8 *) wpabuf_put(buf, 0) - len - 1;
+
+out:
+       os_free(padded_data);
+       os_free(encrypted_data);
+       return ret;
+}
+
+
+int pasn_parse_encrypted_data(struct pasn_data *pasn, const u8 *data,
+                             size_t len)
+{
+       int ret = -1;
+       u8 *buf;
+       u16 buf_len;
+       struct ieee802_11_elems elems;
+       const struct ieee80211_mgmt *mgmt =
+               (const struct ieee80211_mgmt *) data;
+
+       if (len < 24 + 6 ||
+           ieee802_11_parse_elems(mgmt->u.auth.variable,
+                                  len - offsetof(struct ieee80211_mgmt,
+                                                 u.auth.variable),
+                                  &elems, 0) == ParseFailed) {
+               wpa_printf(MSG_DEBUG,
+                          "PASN: Failed parsing Authentication frame");
+               return -1;
+       }
+
+       if (!elems.pasn_encrypted_data || elems.pasn_encrypted_data_len < 8 ||
+           elems.pasn_encrypted_data_len % 8) {
+               wpa_printf(MSG_DEBUG, "PASN: No encrypted elements");
+               return 0;
+       }
+
+       buf_len = elems.pasn_encrypted_data_len - 8;
+
+       buf = os_malloc(buf_len);
+       if (!buf)
+               return -1;
+
+       ret = aes_unwrap(pasn->ptk.kek, pasn->ptk.kek_len, buf_len / 8,
+                        elems.pasn_encrypted_data, buf);
+       if (ret)
+               wpa_printf(MSG_DEBUG, "PASN: AES unwrap failed, ret=%d", ret);
+       else if (pasn->parse_data_element && pasn->cb_ctx)
+               ret = pasn->parse_data_element(pasn->cb_ctx, buf, buf_len);
+
+       os_free(buf);
+       return ret;
+}
index 7b7c73792d8af69048acbb8413732ce7728527f0..4a5baf0cabae79dc70aeb948bd07aa3e8dcdc471 100644 (file)
@@ -151,6 +151,10 @@ struct pasn_data {
         */
        int (*validate_custom_pmkid)(void *ctx, const u8 *addr,
                                     const u8 *pmkid);
+
+       int (*prepare_data_element)(void *ctx, const u8 *peer_addr);
+
+       int (*parse_data_element)(void *ctx, const u8 *data, size_t len);
 };
 
 /* Initiator */
@@ -246,6 +250,10 @@ int pasn_get_cipher(struct pasn_data *pasn);
 size_t pasn_get_pmk_len(struct pasn_data *pasn);
 u8 * pasn_get_pmk(struct pasn_data *pasn);
 struct wpa_ptk * pasn_get_ptk(struct pasn_data *pasn);
+int pasn_add_encrypted_data(struct pasn_data *pasn, struct wpabuf *buf,
+                           const u8 *data, size_t data_len);
+int pasn_parse_encrypted_data(struct pasn_data *pasn, const u8 *data,
+                             size_t len);
 
 #ifdef __cplusplus
 }
index ce1055b1b1630353ea2edcfd51612e0087b10e33..c8e5b3d99f2ab44e2ee7beb4489d698ac98baa68 100644 (file)
@@ -716,6 +716,11 @@ static struct wpabuf * wpas_pasn_build_auth_3(struct pasn_data *pasn)
        wpabuf_free(wrapped_data_buf);
        wrapped_data_buf = NULL;
 
+       if (pasn->prepare_data_element && pasn->cb_ctx)
+               pasn->prepare_data_element(pasn->cb_ctx, pasn->peer_addr);
+
+       wpa_pasn_add_extra_ies(buf, pasn->extra_ies, pasn->extra_ies_len);
+
        /* Add the MIC */
        mic_len = pasn_mic_len(pasn->akmp, pasn->cipher);
        wpabuf_put_u8(buf, WLAN_EID_MIC);
@@ -1386,6 +1391,11 @@ int wpa_pasn_auth_rx(struct pasn_data *pasn, const u8 *data, size_t len,
 
        wpa_printf(MSG_DEBUG, "PASN: Success verifying Authentication frame");
 
+       if (pasn_parse_encrypted_data(pasn, data, len) < 0) {
+               wpa_printf(MSG_DEBUG, "PASN: Encrypted data processing failed");
+               goto fail;
+       }
+
        frame = wpas_pasn_build_auth_3(pasn);
        if (!frame) {
                wpa_printf(MSG_DEBUG, "PASN: Failed building 3rd auth frame");
index e344898df2935dac923cdbe7c5e9c3ae249236de..12d00ef3e5b9666965e55f1dad31c2cb0844afe1 100644 (file)
@@ -561,6 +561,9 @@ int handle_auth_pasn_resp(struct pasn_data *pasn, const u8 *own_addr,
        if (rsnxe_ie)
                wpabuf_put_data(buf, rsnxe_ie, 2 + rsnxe_ie[1]);
 
+       if (pasn->prepare_data_element && pasn->cb_ctx)
+               pasn->prepare_data_element(pasn->cb_ctx, peer_addr);
+
        wpa_pasn_add_extra_ies(buf, pasn->extra_ies, pasn->extra_ies_len);
 
        /* Add the mic */
@@ -1086,6 +1089,11 @@ int handle_auth_pasn_3(struct pasn_data *pasn, const u8 *own_addr,
                wpabuf_free(wrapped_data);
        }
 
+       if (pasn_parse_encrypted_data(pasn, (const u8 *) mgmt, len) < 0) {
+               wpa_printf(MSG_DEBUG, "PASN: Encrypted data processing failed");
+               goto fail;
+       }
+
        wpa_printf(MSG_INFO,
                   "PASN: Success handling transaction == 3. Store PTK");
        return 0;