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);
}
+#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()
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);
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);
}
+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];
} 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)