[PATCH 4/4] wpa_supplicant: Add GTK RSC relaxation workaround
Ilan Peer
ilan.peer
Wed Oct 14 02:26:33 PDT 2015
From: Max Stepanov <Max.Stepanov at intel.com>
Some APs may send RSC octets in EAP message 3 of 4-Way Handshake or in
EAP message 1 of Group Key Handshake in the opposite order. Thus, after a
successful EAP authentication the TSC values of received multicast packets,
such as DHCP, don't match the RSC one and as a result these packets are
dropped on replay attack TSC verification. An example of such AP is
Sapido RB-1732.
Workaournd this by setting RSC octets to 0 on GTK installation if the AP
RSC value is identified as a potentially having the byte order issue.
The wpa_rsc_relaxation global configuration property allows to disable
the GTK RSC workaround if it's not needed.
Signed-off-by: Max Stepanov <Max.Stepanov at intel.com>
---
src/rsn_supp/wpa.c | 55 +++++++++++++++++++++++++++++++++++++++++---
src/rsn_supp/wpa.h | 1 +
wpa_supplicant/config.c | 3 +++
wpa_supplicant/config.h | 12 ++++++++++
wpa_supplicant/config_file.c | 4 ++++
wpa_supplicant/wpas_glue.c | 9 ++++++++
6 files changed, 81 insertions(+), 3 deletions(-)
diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index f1f65c6..39e4850 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -1,6 +1,7 @@
/*
* WPA Supplicant - WPA state machine and EAPOL-Key processing
* Copyright (c) 2003-2015, Jouni Malinen <j at w1.fi>
+ * Copyright(c) 2015 Intel Deutschland GmbH
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -22,6 +23,7 @@
#include "wpa_ie.h"
#include "peerkey.h"
+static const u8 null_rsc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
/**
* wpa_eapol_key_send - Send WPA/RSN EAPOL-Key message
@@ -604,7 +606,6 @@ static int wpa_supplicant_install_ptk(struct wpa_sm *sm,
int keylen, rsclen;
enum wpa_alg alg;
const u8 *key_rsc;
- u8 null_rsc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
if (!sm->tk_to_set) {
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
@@ -761,12 +762,51 @@ static int wpa_supplicant_gtk_tx_bit_workaround(const struct wpa_sm *sm,
}
+static int wpa_supplicant_get_wpa_rsc_relaxation(const struct wpa_sm *sm)
+{
+ if (sm->ctx->get_wpa_rsc_relaxation)
+ return sm->ctx->get_wpa_rsc_relaxation(sm->ctx->ctx);
+ return 0;
+}
+
+
+static int wpa_supplicant_rsc_relaxation(const struct wpa_sm *sm,
+ const u8 *rsc)
+{
+ int rsclen;
+
+ if (wpa_supplicant_get_wpa_rsc_relaxation(sm))
+ return 0;
+
+ rsclen = wpa_cipher_rsc_len(sm->group_cipher);
+
+ /*
+ * try to detect RSC (endian) corruption issue where the AP sends
+ * the RSC bytes in EAPOL KEY message in the wrong order, both if
+ * it's actually a 6-byte field (as it should be) and if it treats
+ * it as an 8-byte field.
+ * An AP model known to have this bug is the Sapido RB-1632.
+ */
+ if (rsclen == 6 && ((rsc[5] && !rsc[0]) || rsc[6] || rsc[7])) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
+ "RSC %.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x is likely bogus, using 0",
+ rsc[0], rsc[1], rsc[2], rsc[3],
+ rsc[4], rsc[5], rsc[6], rsc[7]);
+
+ return 1;
+ }
+
+ return 0;
+}
+
+
static int wpa_supplicant_pairwise_gtk(struct wpa_sm *sm,
const struct wpa_eapol_key *key,
const u8 *gtk, size_t gtk_len,
int key_info)
{
struct wpa_gtk_data gd;
+ const u8 *key_rsc;
/*
* IEEE Std 802.11i-2004 - 8.5.2 EAPOL-Key frames - Figure 43x
@@ -792,11 +832,15 @@ static int wpa_supplicant_pairwise_gtk(struct wpa_sm *sm,
os_memcpy(gd.gtk, gtk, gtk_len);
gd.gtk_len = gtk_len;
+ key_rsc = key->key_rsc;
+ if (wpa_supplicant_rsc_relaxation(sm, key->key_rsc))
+ key_rsc = null_rsc;
+
if (sm->group_cipher != WPA_CIPHER_GTK_NOT_USED &&
(wpa_supplicant_check_group_cipher(sm, sm->group_cipher,
gtk_len, gtk_len,
&gd.key_rsc_len, &gd.alg) ||
- wpa_supplicant_install_gtk(sm, &gd, key->key_rsc))) {
+ wpa_supplicant_install_gtk(sm, &gd, key_rsc))) {
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
"RSN: Failed to install GTK");
os_memset(&gd, 0, sizeof(gd));
@@ -1461,6 +1505,7 @@ static void wpa_supplicant_process_1_of_2(struct wpa_sm *sm,
u16 key_info;
int rekey, ret;
struct wpa_gtk_data gd;
+ const u8 *key_rsc;
if (!sm->msg_3_of_4_ok) {
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
@@ -1491,7 +1536,11 @@ static void wpa_supplicant_process_1_of_2(struct wpa_sm *sm,
if (ret)
goto failed;
- if (wpa_supplicant_install_gtk(sm, &gd, key->key_rsc) ||
+ key_rsc = key->key_rsc;
+ if (wpa_supplicant_rsc_relaxation(sm, key->key_rsc))
+ key_rsc = null_rsc;
+
+ if (wpa_supplicant_install_gtk(sm, &gd, key_rsc) ||
wpa_supplicant_send_2_of_2(sm, key, ver, key_info))
goto failed;
os_memset(&gd, 0, sizeof(gd));
diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h
index e163b70..2ba100d 100644
--- a/src/rsn_supp/wpa.h
+++ b/src/rsn_supp/wpa.h
@@ -77,6 +77,7 @@ struct wpa_sm_ctx {
const u8 *kck, size_t kck_len,
const u8 *replay_ctr);
int (*key_mgmt_set_pmk)(void *ctx, const u8 *pmk, size_t pmk_len);
+ int (*get_wpa_rsc_relaxation)(void *ctx);
};
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index b1adab7..d20fc01 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -3546,6 +3546,8 @@ struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
if (driver_param)
config->driver_param = os_strdup(driver_param);
+ config->wpa_rsc_relaxation = DEFAULT_WPA_RSC_RELAXATION;
+
return config;
}
@@ -4246,6 +4248,7 @@ static const struct global_parse_data global_fields[] = {
{ INT_RANGE(fst_priority, 1, FST_MAX_PRIO_VALUE), 0 },
{ INT_RANGE(fst_llt, 1, FST_MAX_LLT_MS), 0 },
#endif /* CONFIG_FST */
+ { INT_RANGE(wpa_rsc_relaxation, 0, 1), 0 },
};
#undef FUNC
diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h
index 68d64fa..6901a33 100644
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -40,6 +40,8 @@
#define DEFAULT_CERT_IN_CB 1
#define DEFAULT_P2P_GO_CTWINDOW 0
+#define DEFAULT_WPA_RSC_RELAXATION 1
+
#include "config_ssid.h"
#include "wps/wps.h"
#include "common/ieee802_11_defs.h"
@@ -1252,6 +1254,16 @@ struct wpa_config {
* interface.
*/
int fst_llt;
+
+ /**
+ * wpa_rsc_relaxation - RSC relaxation on GTK installation
+ *
+ * Values:
+ * 0 - use the EAPOL KEY RSC value on GTK installation
+ * 1 - use the null RSC if a bogus RSC value is detected in message 3
+ * of 4-Way Handshake or message 1 of Group Key Handshake.
+ */
+ int wpa_rsc_relaxation;
};
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index fb438ea..cbc79a8 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -1299,6 +1299,10 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
if (config->wps_priority)
fprintf(f, "wps_priority=%d\n", config->wps_priority);
+
+ if (config->wpa_rsc_relaxation != DEFAULT_WPA_RSC_RELAXATION)
+ fprintf(f, "wpa_rsc_relaxation=%u\n",
+ config->wpa_rsc_relaxation);
}
#endif /* CONFIG_NO_CONFIG_WRITE */
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index 29c22ba..39207ed 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -1030,6 +1030,14 @@ static int wpa_supplicant_key_mgmt_set_pmk(void *ctx, const u8 *pmk,
}
+static int wpa_supplicant_wpa_rsc_relaxation(void *ctx)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+
+ return wpa_s->conf->wpa_rsc_relaxation;
+}
+
+
int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s)
{
#ifndef CONFIG_NO_WPA
@@ -1076,6 +1084,7 @@ int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s)
#endif /* CONFIG_TDLS */
ctx->set_rekey_offload = wpa_supplicant_set_rekey_offload;
ctx->key_mgmt_set_pmk = wpa_supplicant_key_mgmt_set_pmk;
+ ctx->get_wpa_rsc_relaxation = wpa_supplicant_wpa_rsc_relaxation;
wpa_s->wpa = wpa_sm_init(ctx);
if (wpa_s->wpa == NULL) {
--
1.9.1
More information about the Hostap
mailing list