]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Add TEST_RSNXE_DATA for RSNXE testing of AP functionality
authorVeerendranath Jakkam <quic_vjakkam@quicinc.com>
Mon, 9 Sep 2024 20:01:28 +0000 (01:31 +0530)
committerJouni Malinen <j@w1.fi>
Thu, 19 Sep 2024 10:16:36 +0000 (13:16 +0300)
Add support to set test data in the default RSNXE with wpa_supplicant
control interface command "TEST_RSNXE_DATA <data hexdump> <mask
hexdump>". This can be used to do protocol testing of AP side processing
of RSNXE.

Signed-off-by: Veerendranath Jakkam <quic_vjakkam@quicinc.com>
src/rsn_supp/wpa.c
src/rsn_supp/wpa.h
src/rsn_supp/wpa_ft.c
src/rsn_supp/wpa_i.h
wpa_supplicant/ctrl_iface.c
wpa_supplicant/wpa_supplicant_i.h

index b7518f9b6f93d29b69ad3a9e7826d5a071d59361..ae7c4d51d14876b97e57a310615eed5b6d2445c3 100644 (file)
@@ -4375,6 +4375,8 @@ void wpa_sm_deinit(struct wpa_sm *sm)
        wpabuf_free(sm->test_assoc_ie);
        wpabuf_free(sm->test_eapol_m2_elems);
        wpabuf_free(sm->test_eapol_m4_elems);
+       wpabuf_free(sm->test_rsnxe_data);
+       wpabuf_free(sm->test_rsnxe_mask);
 #endif /* CONFIG_TESTING_OPTIONS */
 #ifdef CONFIG_FILS_SK_PFS
        crypto_ecdh_deinit(sm->fils_ecdh);
@@ -5234,6 +5236,76 @@ int wpa_sm_set_assoc_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len)
 }
 
 
+#ifdef CONFIG_TESTING_OPTIONS
+
+int wpa_sm_set_test_rsnxe_data(struct wpa_sm *sm, struct wpabuf *data,
+                              struct wpabuf *mask)
+{
+       size_t data_len = 0, mask_len = 0;
+
+       wpabuf_free(sm->test_rsnxe_data);
+       sm->test_rsnxe_data = NULL;
+       wpabuf_free(sm->test_rsnxe_mask);
+       sm->test_rsnxe_mask = NULL;
+
+       if (!data && !mask)
+               return 0;
+
+       if (data)
+               data_len = wpabuf_len(data);
+       if (mask)
+               mask_len = wpabuf_len(mask);
+
+       if (data_len != mask_len || data_len > 255)
+               return -1;
+
+       sm->test_rsnxe_data = data;
+       sm->test_rsnxe_mask = mask;
+
+       return 0;
+}
+
+
+static int wpa_set_test_rsnxe_data(struct wpa_sm *sm, u8 *rsnxe,
+                                  size_t orig_len, size_t max_len)
+{
+       const u8 *data, *mask;
+       size_t i, data_len;
+
+       if (!sm->test_rsnxe_data || !sm->test_rsnxe_mask)
+               return orig_len;
+
+       mask = wpabuf_head(sm->test_rsnxe_mask);
+       data = wpabuf_head(sm->test_rsnxe_data);
+       data_len = wpabuf_len(sm->test_rsnxe_data);
+       if (max_len < data_len + 2) {
+               wpa_printf(MSG_ERROR, "Couldn't fit RSNXE test data");
+               return -1;
+       }
+
+       /* Set data after original RSNXE to zero */
+       if (orig_len < data_len + 2)
+               os_memset(&rsnxe[orig_len], 0, data_len + 2 - orig_len);
+
+       /* Set EID and length fields */
+       *rsnxe++ = WLAN_EID_RSNX;
+       *rsnxe++ = data_len;
+
+       /* Preserve original RSNXE bit value when mask bit is zero */
+       for (i = 0; i < data_len; i++) {
+               if (!mask[i])
+                       continue;
+
+               rsnxe[i] &= ~mask[i];
+               rsnxe[i] |= data[i] & mask[i];
+       }
+
+       return data_len + 2;
+}
+
+#endif /* CONFIG_TESTING_OPTIONS */
+
+
 /**
  * wpa_sm_set_assoc_rsnxe_default - Generate own RSNXE from configuration
  * @sm: Pointer to WPA state machine data from wpa_sm_init()
@@ -5252,6 +5324,11 @@ int wpa_sm_set_assoc_rsnxe_default(struct wpa_sm *sm, u8 *rsnxe,
        res = wpa_gen_rsnxe(sm, rsnxe, *rsnxe_len);
        if (res < 0)
                return -1;
+#ifdef CONFIG_TESTING_OPTIONS
+       res = wpa_set_test_rsnxe_data(sm, rsnxe, res, *rsnxe_len);
+       if (res < 0)
+               return -1;
+#endif /* CONFIG_TESTING_OPTIONS */
        *rsnxe_len = res;
 
        wpa_hexdump(MSG_DEBUG, "RSN: Set own RSNXE default", rsnxe, *rsnxe_len);
index d8112c4c22aacb75fd6de0ac09cb55033762abe5..57ee0a63532f49a49a58f3467106f2a997bad755 100644 (file)
@@ -626,6 +626,8 @@ void wpa_sm_set_test_assoc_ie(struct wpa_sm *sm, struct wpabuf *buf);
 void wpa_sm_set_test_eapol_m2_elems(struct wpa_sm *sm, struct wpabuf *buf);
 void wpa_sm_set_test_eapol_m4_elems(struct wpa_sm *sm, struct wpabuf *buf);
 const u8 * wpa_sm_get_anonce(struct wpa_sm *sm);
+int wpa_sm_set_test_rsnxe_data(struct wpa_sm *sm, struct wpabuf *data,
+                              struct wpabuf *mask);
 unsigned int wpa_sm_get_key_mgmt(struct wpa_sm *sm);
 
 struct wpabuf * fils_build_auth(struct wpa_sm *sm, int dh_group, const u8 *md);
index 9fb5668efc9146701a8255eabfb0ca1c1ff4520e..ecfdb4d70b1f6369bbab425d9994af269193ec0d 100644 (file)
@@ -215,7 +215,7 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
        struct rsn_mdie *mdie;
        struct rsn_ie_hdr *rsnie;
        int mdie_len;
-       u8 rsnxe[10];
+       u8 rsnxe[257];
        size_t rsnxe_len;
        int rsnxe_used;
        int res;
index c2ea95bb742380b0677fee252ec55cf2b0e85897..2fd08b0f231cd910888e52efac5dc9bc558a1ea4 100644 (file)
@@ -188,6 +188,8 @@ struct wpa_sm {
        struct wpabuf *test_assoc_ie;
        struct wpabuf *test_eapol_m2_elems;
        struct wpabuf *test_eapol_m4_elems;
+       struct wpabuf *test_rsnxe_data;
+       struct wpabuf *test_rsnxe_mask;
        int ft_rsnxe_used;
        unsigned int oci_freq_override_eapol;
        unsigned int oci_freq_override_eapol_g2;
index b496ca3e64638cd5f3aab16e1f340354133685e6..5b5ab57bfc27a6460489c41697416c575c6009e8 100644 (file)
@@ -8931,6 +8931,7 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
        wpa_sm_set_test_assoc_ie(wpa_s->wpa, NULL);
        wpa_sm_set_test_eapol_m2_elems(wpa_s->wpa, NULL);
        wpa_sm_set_test_eapol_m4_elems(wpa_s->wpa, NULL);
+       wpa_sm_set_test_rsnxe_data(wpa_s->wpa, NULL, NULL);
        wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_ENCRYPT_EAPOL_M2, 0);
        wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_ENCRYPT_EAPOL_M4, 0);
        os_free(wpa_s->get_pref_freq_list_override);
@@ -10303,6 +10304,29 @@ static int wpas_ctrl_test_eapol_m4_elems(struct wpa_supplicant *wpa_s,
 }
 
 
+static int wpas_ctrl_test_rsnxe_data(struct wpa_supplicant *wpa_s,
+                                    const char *cmd)
+{
+       struct wpabuf *data = NULL, *mask = NULL;
+       char *pos;
+
+       pos = os_strchr(cmd, ' ');
+       if (!pos)
+               return -1;
+       *pos++ = '\0';
+
+       if (wpas_get_hex_buf(cmd, &data) < 0 ||
+           wpas_get_hex_buf(pos, &mask) < 0 ||
+           wpa_sm_set_test_rsnxe_data(wpa_s->wpa, data, mask) < 0) {
+               wpabuf_free(data);
+               wpabuf_free(mask);
+               return -1;
+       }
+
+       return 0;
+}
+
+
 static int wpas_ctrl_reset_pn(struct wpa_supplicant *wpa_s)
 {
        u8 zero[WPA_TK_MAX_LEN];
@@ -13388,6 +13412,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
        } else if (os_strncmp(buf, "ML_PROBE_REQ ", 13) == 0) {
                if (wpas_ctrl_ml_probe(wpa_s, buf + 13))
                        reply_len = -1;
+       } else if (os_strncmp(buf, "TEST_RSNXE_DATA ", 16) == 0) {
+               if (wpas_ctrl_test_rsnxe_data(wpa_s, buf + 16) < 0)
+                       reply_len = -1;
 #endif /* CONFIG_TESTING_OPTIONS */
        } else if (os_strncmp(buf, "VENDOR_ELEM_ADD ", 16) == 0) {
                if (wpas_ctrl_vendor_elem_add(wpa_s, buf + 16) < 0)
index 36194c97489908a44d1e9b530037f3cc053c4549..011cdf2dd455ceebbc8d1823cee9e74aa5cebb8c 100644 (file)
@@ -827,7 +827,7 @@ struct wpa_supplicant {
        int eapol_received; /* number of EAPOL packets received after the
                             * previous association event */
 
-       u8 rsnxe[20];
+       u8 rsnxe[257];
        size_t rsnxe_len;
 
        struct scard_data *scard;