]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Supplicant side testing functionality for EAPOL-Key Key Data field
authorJouni Malinen <quic_jouni@quicinc.com>
Tue, 16 Jan 2024 14:03:34 +0000 (16:03 +0200)
committerJouni Malinen <j@w1.fi>
Tue, 16 Jan 2024 14:38:30 +0000 (16:38 +0200)
Allow additional elements and KDEs to be added to EAPOL-Key msg 2/4 and
4/4. This is for testing purposes to enable a convenient mechanism for
testing Authenticator behavior with either potential future extensions or
incorrect Supplicant behavior.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
src/rsn_supp/wpa.c
src/rsn_supp/wpa.h
src/rsn_supp/wpa_i.h
wpa_supplicant/ctrl_iface.c

index 950d91bfd77ae253fe9d02ad45d4772a9d19444e..e2e05eb455c667ceacd87f3ac8115fbb5c6779f6 100644 (file)
@@ -521,7 +521,7 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
                               const u8 *wpa_ie, size_t wpa_ie_len,
                               struct wpa_ptk *ptk)
 {
-       size_t mic_len, hdrlen, rlen;
+       size_t mic_len, hdrlen, rlen, extra_len = 0;
        struct wpa_eapol_key *reply;
        u8 *rbuf, *key_mic;
        u8 *rsn_ie_buf = NULL;
@@ -573,10 +573,15 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
 
        wpa_hexdump(MSG_DEBUG, "WPA: WPA IE for msg 2/4", wpa_ie, wpa_ie_len);
 
+#ifdef CONFIG_TESTING_OPTIONS
+       if (sm->test_eapol_m2_elems)
+               extra_len = wpabuf_len(sm->test_eapol_m2_elems);
+#endif /* CONFIG_TESTING_OPTIONS */
+
        mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len);
        hdrlen = sizeof(*reply) + mic_len + 2;
        rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY,
-                                 NULL, hdrlen + wpa_ie_len,
+                                 NULL, hdrlen + wpa_ie_len + extra_len,
                                  &rlen, (void *) &reply);
        if (rbuf == NULL) {
                os_free(rsn_ie_buf);
@@ -604,9 +609,17 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
                    WPA_REPLAY_COUNTER_LEN);
 
        key_mic = (u8 *) (reply + 1);
-       WPA_PUT_BE16(key_mic + mic_len, wpa_ie_len); /* Key Data Length */
+       /* Key Data Length */
+       WPA_PUT_BE16(key_mic + mic_len, wpa_ie_len + extra_len);
        os_memcpy(key_mic + mic_len + 2, wpa_ie, wpa_ie_len); /* Key Data */
        os_free(rsn_ie_buf);
+#ifdef CONFIG_TESTING_OPTIONS
+       if (sm->test_eapol_m2_elems) {
+               os_memcpy(key_mic + mic_len + 2 + wpa_ie_len,
+                         wpabuf_head(sm->test_eapol_m2_elems),
+                         wpabuf_len(sm->test_eapol_m2_elems));
+       }
+#endif /* CONFIG_TESTING_OPTIONS */
 
        os_memcpy(reply->key_nonce, nonce, WPA_NONCE_LEN);
 
@@ -2154,7 +2167,7 @@ int wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst,
        struct wpa_eapol_key *reply;
        u8 *rbuf, *key_mic;
        u8 *kde = NULL;
-       size_t kde_len = 0;
+       size_t kde_len = 0, extra_len = 0;
 
        if (sm->mlo.valid_links) {
                u8 *pos;
@@ -2171,10 +2184,16 @@ int wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst,
                kde_len = pos - kde;
        }
 
+#ifdef CONFIG_TESTING_OPTIONS
+       if (sm->test_eapol_m4_elems)
+               extra_len = wpabuf_len(sm->test_eapol_m4_elems);
+#endif /* CONFIG_TESTING_OPTIONS */
+
        mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len);
        hdrlen = sizeof(*reply) + mic_len + 2;
        rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
-                                 hdrlen + kde_len, &rlen, (void *) &reply);
+                                 hdrlen + kde_len + extra_len, &rlen,
+                                 (void *) &reply);
        if (!rbuf) {
                os_free(kde);
                return -1;
@@ -2198,12 +2217,21 @@ int wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst,
                  WPA_REPLAY_COUNTER_LEN);
 
        key_mic = (u8 *) (reply + 1);
-       WPA_PUT_BE16(key_mic + mic_len, kde_len); /* Key Data length */
+       /* Key Data length */
+       WPA_PUT_BE16(key_mic + mic_len, kde_len + extra_len);
        if (kde) {
                os_memcpy(key_mic + mic_len + 2, kde, kde_len); /* Key Data */
                os_free(kde);
        }
 
+#ifdef CONFIG_TESTING_OPTIONS
+       if (sm->test_eapol_m4_elems) {
+               os_memcpy(key_mic + mic_len + 2 + kde_len,
+                         wpabuf_head(sm->test_eapol_m4_elems),
+                         wpabuf_len(sm->test_eapol_m4_elems));
+       }
+#endif /* CONFIG_TESTING_OPTIONS */
+
        wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 4/4");
        return wpa_eapol_key_send(sm, ptk, ver, dst, ETH_P_EAPOL, rbuf, rlen,
                                  key_mic);
@@ -4039,6 +4067,8 @@ void wpa_sm_deinit(struct wpa_sm *sm)
 #endif /* CONFIG_IEEE80211R */
 #ifdef CONFIG_TESTING_OPTIONS
        wpabuf_free(sm->test_assoc_ie);
+       wpabuf_free(sm->test_eapol_m2_elems);
+       wpabuf_free(sm->test_eapol_m4_elems);
 #endif /* CONFIG_TESTING_OPTIONS */
 #ifdef CONFIG_FILS_SK_PFS
        crypto_ecdh_deinit(sm->fils_ecdh);
@@ -5204,6 +5234,20 @@ 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)
+{
+       wpabuf_free(sm->test_eapol_m2_elems);
+       sm->test_eapol_m2_elems = buf;
+}
+
+
+void wpa_sm_set_test_eapol_m4_elems(struct wpa_sm *sm, struct wpabuf *buf)
+{
+       wpabuf_free(sm->test_eapol_m4_elems);
+       sm->test_eapol_m4_elems = buf;
+}
+
+
 const u8 * wpa_sm_get_anonce(struct wpa_sm *sm)
 {
        return sm->anonce;
index 47a86b04b5f35b7e2c26334d6601f4ed6a0966c6..d99e5f676bddb9099a36635f950470015f7c382b 100644 (file)
@@ -585,6 +585,8 @@ extern unsigned int tdls_testing;
 
 int wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 subelem_id, u8 *buf);
 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);
 unsigned int wpa_sm_get_key_mgmt(struct wpa_sm *sm);
 
index 5fe6182ff711096337172893e5ad7a513ab7e036..aa1d739c5fc49a2e368ab9a87572b47f4501966c 100644 (file)
@@ -182,6 +182,8 @@ struct wpa_sm {
 
 #ifdef CONFIG_TESTING_OPTIONS
        struct wpabuf *test_assoc_ie;
+       struct wpabuf *test_eapol_m2_elems;
+       struct wpabuf *test_eapol_m4_elems;
        int ft_rsnxe_used;
        unsigned int oci_freq_override_eapol;
        unsigned int oci_freq_override_eapol_g2;
index 0708fbdff456428408a98bd1acf6d80639c5213d..8317b1a7a022690a7156d892eff488429a80b878 100644 (file)
@@ -8852,6 +8852,8 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
        wpa_s->ft_rsnxe_used = 0;
        wpa_s->reject_btm_req_reason = 0;
        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);
        os_free(wpa_s->get_pref_freq_list_override);
        wpa_s->get_pref_freq_list_override = NULL;
        wpabuf_free(wpa_s->sae_commit_override);
@@ -10152,13 +10154,12 @@ static int wpas_ctrl_event_test(struct wpa_supplicant *wpa_s, const char *cmd)
 }
 
 
-static int wpas_ctrl_test_assoc_ie(struct wpa_supplicant *wpa_s,
-                                  const char *cmd)
+static int wpas_get_hex_buf(const char *val, struct wpabuf **ret)
 {
        struct wpabuf *buf;
        size_t len;
 
-       len = os_strlen(cmd);
+       len = os_strlen(val);
        if (len & 1)
                return -1;
        len /= 2;
@@ -10167,20 +10168,56 @@ static int wpas_ctrl_test_assoc_ie(struct wpa_supplicant *wpa_s,
                buf = NULL;
        } else {
                buf = wpabuf_alloc(len);
-               if (buf == NULL)
+               if (!buf)
                        return -1;
 
-               if (hexstr2bin(cmd, wpabuf_put(buf, len), len) < 0) {
+               if (hexstr2bin(val, wpabuf_put(buf, len), len) < 0) {
                        wpabuf_free(buf);
                        return -1;
                }
        }
 
+       *ret = buf;
+       return 0;
+}
+
+
+static int wpas_ctrl_test_assoc_ie(struct wpa_supplicant *wpa_s,
+                                  const char *cmd)
+{
+       struct wpabuf *buf;
+
+       if (wpas_get_hex_buf(cmd, &buf) < 0)
+               return -1;
        wpa_sm_set_test_assoc_ie(wpa_s->wpa, buf);
        return 0;
 }
 
 
+static int wpas_ctrl_test_eapol_m2_elems(struct wpa_supplicant *wpa_s,
+                                        const char *cmd)
+{
+       struct wpabuf *buf;
+
+       if (wpas_get_hex_buf(cmd, &buf) < 0)
+               return -1;
+       wpa_sm_set_test_eapol_m2_elems(wpa_s->wpa, buf);
+       return 0;
+}
+
+
+static int wpas_ctrl_test_eapol_m4_elems(struct wpa_supplicant *wpa_s,
+                                        const char *cmd)
+{
+       struct wpabuf *buf;
+
+       if (wpas_get_hex_buf(cmd, &buf) < 0)
+               return -1;
+       wpa_sm_set_test_eapol_m4_elems(wpa_s->wpa, buf);
+       return 0;
+}
+
+
 static int wpas_ctrl_reset_pn(struct wpa_supplicant *wpa_s)
 {
        u8 zero[WPA_TK_MAX_LEN];
@@ -12880,6 +12917,12 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
        } else if (os_strncmp(buf, "TEST_ASSOC_IE ", 14) == 0) {
                if (wpas_ctrl_test_assoc_ie(wpa_s, buf + 14) < 0)
                        reply_len = -1;
+       } else if (os_strncmp(buf, "TEST_EAPOL_M2_ELEMS ", 20) == 0) {
+               if (wpas_ctrl_test_eapol_m2_elems(wpa_s, buf + 20) < 0)
+                       reply_len = -1;
+       } else if (os_strncmp(buf, "TEST_EAPOL_M4_ELEMS ", 20) == 0) {
+               if (wpas_ctrl_test_eapol_m4_elems(wpa_s, buf + 20) < 0)
+                       reply_len = -1;
        } else if (os_strcmp(buf, "RESET_PN") == 0) {
                if (wpas_ctrl_reset_pn(wpa_s) < 0)
                        reply_len = -1;