Supplicant side testing functionality for EAPOL-Key Key Data field
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>
This commit is contained in:
parent
f7a903654f
commit
f591732af7
4 changed files with 102 additions and 11 deletions
|
@ -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,
|
const u8 *wpa_ie, size_t wpa_ie_len,
|
||||||
struct wpa_ptk *ptk)
|
struct wpa_ptk *ptk)
|
||||||
{
|
{
|
||||||
size_t mic_len, hdrlen, rlen;
|
size_t mic_len, hdrlen, rlen, extra_len = 0;
|
||||||
struct wpa_eapol_key *reply;
|
struct wpa_eapol_key *reply;
|
||||||
u8 *rbuf, *key_mic;
|
u8 *rbuf, *key_mic;
|
||||||
u8 *rsn_ie_buf = NULL;
|
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);
|
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);
|
mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len);
|
||||||
hdrlen = sizeof(*reply) + mic_len + 2;
|
hdrlen = sizeof(*reply) + mic_len + 2;
|
||||||
rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY,
|
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);
|
&rlen, (void *) &reply);
|
||||||
if (rbuf == NULL) {
|
if (rbuf == NULL) {
|
||||||
os_free(rsn_ie_buf);
|
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);
|
WPA_REPLAY_COUNTER_LEN);
|
||||||
|
|
||||||
key_mic = (u8 *) (reply + 1);
|
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_memcpy(key_mic + mic_len + 2, wpa_ie, wpa_ie_len); /* Key Data */
|
||||||
os_free(rsn_ie_buf);
|
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);
|
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;
|
struct wpa_eapol_key *reply;
|
||||||
u8 *rbuf, *key_mic;
|
u8 *rbuf, *key_mic;
|
||||||
u8 *kde = NULL;
|
u8 *kde = NULL;
|
||||||
size_t kde_len = 0;
|
size_t kde_len = 0, extra_len = 0;
|
||||||
|
|
||||||
if (sm->mlo.valid_links) {
|
if (sm->mlo.valid_links) {
|
||||||
u8 *pos;
|
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;
|
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);
|
mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len);
|
||||||
hdrlen = sizeof(*reply) + mic_len + 2;
|
hdrlen = sizeof(*reply) + mic_len + 2;
|
||||||
rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
|
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) {
|
if (!rbuf) {
|
||||||
os_free(kde);
|
os_free(kde);
|
||||||
return -1;
|
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);
|
WPA_REPLAY_COUNTER_LEN);
|
||||||
|
|
||||||
key_mic = (u8 *) (reply + 1);
|
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) {
|
if (kde) {
|
||||||
os_memcpy(key_mic + mic_len + 2, kde, kde_len); /* Key Data */
|
os_memcpy(key_mic + mic_len + 2, kde, kde_len); /* Key Data */
|
||||||
os_free(kde);
|
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");
|
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,
|
return wpa_eapol_key_send(sm, ptk, ver, dst, ETH_P_EAPOL, rbuf, rlen,
|
||||||
key_mic);
|
key_mic);
|
||||||
|
@ -4039,6 +4067,8 @@ void wpa_sm_deinit(struct wpa_sm *sm)
|
||||||
#endif /* CONFIG_IEEE80211R */
|
#endif /* CONFIG_IEEE80211R */
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
wpabuf_free(sm->test_assoc_ie);
|
wpabuf_free(sm->test_assoc_ie);
|
||||||
|
wpabuf_free(sm->test_eapol_m2_elems);
|
||||||
|
wpabuf_free(sm->test_eapol_m4_elems);
|
||||||
#endif /* CONFIG_TESTING_OPTIONS */
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
#ifdef CONFIG_FILS_SK_PFS
|
#ifdef CONFIG_FILS_SK_PFS
|
||||||
crypto_ecdh_deinit(sm->fils_ecdh);
|
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)
|
const u8 * wpa_sm_get_anonce(struct wpa_sm *sm)
|
||||||
{
|
{
|
||||||
return sm->anonce;
|
return sm->anonce;
|
||||||
|
|
|
@ -585,6 +585,8 @@ extern unsigned int tdls_testing;
|
||||||
|
|
||||||
int wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 subelem_id, u8 *buf);
|
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_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);
|
const u8 * wpa_sm_get_anonce(struct wpa_sm *sm);
|
||||||
unsigned int wpa_sm_get_key_mgmt(struct wpa_sm *sm);
|
unsigned int wpa_sm_get_key_mgmt(struct wpa_sm *sm);
|
||||||
|
|
||||||
|
|
|
@ -182,6 +182,8 @@ struct wpa_sm {
|
||||||
|
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
struct wpabuf *test_assoc_ie;
|
struct wpabuf *test_assoc_ie;
|
||||||
|
struct wpabuf *test_eapol_m2_elems;
|
||||||
|
struct wpabuf *test_eapol_m4_elems;
|
||||||
int ft_rsnxe_used;
|
int ft_rsnxe_used;
|
||||||
unsigned int oci_freq_override_eapol;
|
unsigned int oci_freq_override_eapol;
|
||||||
unsigned int oci_freq_override_eapol_g2;
|
unsigned int oci_freq_override_eapol_g2;
|
||||||
|
|
|
@ -8852,6 +8852,8 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
|
||||||
wpa_s->ft_rsnxe_used = 0;
|
wpa_s->ft_rsnxe_used = 0;
|
||||||
wpa_s->reject_btm_req_reason = 0;
|
wpa_s->reject_btm_req_reason = 0;
|
||||||
wpa_sm_set_test_assoc_ie(wpa_s->wpa, NULL);
|
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);
|
os_free(wpa_s->get_pref_freq_list_override);
|
||||||
wpa_s->get_pref_freq_list_override = NULL;
|
wpa_s->get_pref_freq_list_override = NULL;
|
||||||
wpabuf_free(wpa_s->sae_commit_override);
|
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,
|
static int wpas_get_hex_buf(const char *val, struct wpabuf **ret)
|
||||||
const char *cmd)
|
|
||||||
{
|
{
|
||||||
struct wpabuf *buf;
|
struct wpabuf *buf;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
len = os_strlen(cmd);
|
len = os_strlen(val);
|
||||||
if (len & 1)
|
if (len & 1)
|
||||||
return -1;
|
return -1;
|
||||||
len /= 2;
|
len /= 2;
|
||||||
|
@ -10167,20 +10168,56 @@ static int wpas_ctrl_test_assoc_ie(struct wpa_supplicant *wpa_s,
|
||||||
buf = NULL;
|
buf = NULL;
|
||||||
} else {
|
} else {
|
||||||
buf = wpabuf_alloc(len);
|
buf = wpabuf_alloc(len);
|
||||||
if (buf == NULL)
|
if (!buf)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (hexstr2bin(cmd, wpabuf_put(buf, len), len) < 0) {
|
if (hexstr2bin(val, wpabuf_put(buf, len), len) < 0) {
|
||||||
wpabuf_free(buf);
|
wpabuf_free(buf);
|
||||||
return -1;
|
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);
|
wpa_sm_set_test_assoc_ie(wpa_s->wpa, buf);
|
||||||
return 0;
|
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)
|
static int wpas_ctrl_reset_pn(struct wpa_supplicant *wpa_s)
|
||||||
{
|
{
|
||||||
u8 zero[WPA_TK_MAX_LEN];
|
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) {
|
} else if (os_strncmp(buf, "TEST_ASSOC_IE ", 14) == 0) {
|
||||||
if (wpas_ctrl_test_assoc_ie(wpa_s, buf + 14) < 0)
|
if (wpas_ctrl_test_assoc_ie(wpa_s, buf + 14) < 0)
|
||||||
reply_len = -1;
|
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) {
|
} else if (os_strcmp(buf, "RESET_PN") == 0) {
|
||||||
if (wpas_ctrl_reset_pn(wpa_s) < 0)
|
if (wpas_ctrl_reset_pn(wpa_s) < 0)
|
||||||
reply_len = -1;
|
reply_len = -1;
|
||||||
|
|
Loading…
Reference in a new issue