[wpa_supplicant] Cumulative patch from 6151c9b90
Bug: 130813391
Test: Device boots up and connects to WPA3/OWE wifi networks, run traffic.
Test: Able to turn on/off softap, associate wifi STA, run traffic.
Test: DPP test: act.py -c ../WifiDppConfig.json -tc WifiDppTest
Test: Regression test passed (Bug: 130831127)
6151c9b90 EAP-pwd server: Remove unused srandom() call
d2d1a324c EAP-pwd peer: Fix reassembly buffer handling
fe76f487e EAP-pwd server: Fix reassembly buffer handling
a9d224f56 EAP-pwd server: Fix a memory leak on error path
90ee1bf5f EAP-MSCHAPv2: Propagate GetAsymetricStartKey() failures up from getKey()
824cb5a53 RSN: Ignore IGTK configuration errors with swapped KeyID values
dfdabd917 RSN: Report completion only after IGTK configuration
bce3d4f70 autoscan: Disable when we move above WPA_SCANNING state
eb3234c07 SAE: Use open authentication to reassociate for PMKSA caching
fe01cd006 Fix FILS ERP association event with 4-way HS offload drivers
323a51cc0 nl80211: Handle NL80211_CMD_PROBE_CLIENT command response
28f19a3ae nl80211: More detailed PROBE_CLIENT debug print
31cf52bf2 Do not clear FT IEs twice in sme_deinit()
01ac337b3 Stop SA Query on disconnection
7a206c504 Add debug print on stopping SA Query procedure
710c69238 P2PS: Cleanup pending_p2ps_group flag
0be8b9238 mka: Avoid memory leak in unexpected case in RECEIVE
984d5b7e1 mesh: Fix random llid generation in an error case
10cf866ba mesh: Fix operations after SAE state machine removing the STA
153d4c501 mesh: Fix SAE reauthentication processing
2f6805139 Fix hostapd BSS_TM_REQ handling of bss_term parameter
e6ac47b47 Fix debug print in GET_PREF_FREQ_LIST handler
2e70e807c D-Bus: Fix P2P GroupStarted signal not to use uninitialized IP buffer
c5fff8bbd nl80211: Update assoc_freq and bss->freq based on real association info
091c22771 nl80211: Clear bss->freq on station mode disconnection
cb5db189e Remove the unused crypto_ec_cofactor() function
8b093db2c EAP-pwd: Remove unused checks for cofactor > 1 cases
92e1b96c2 EAP-pwd: Disallow ECC groups with a prime under 256 bits
6fe3ee722 tests: EAP-pwd local failure in crypto_bignum_rand()
6570949b2 OpenSSL: Fix server side openssl_ecdh_curves configuration with 1.0.2
52b1cb5d7 tests: crypto_hash_finish() failure in eap_pwd_kdf()
56ac1f9df RRM: Set last beacon report indication in the last element only
6f484978f Document BSS expiration configurables
8f36c84a2 bsd: Fix a typo in error message
dd1a8cef4 Remove unnecessary copying of SSID and BSSID for external_auth
4ffb0fefe hostapd: Support external authentication offload in AP mode
236e793e7 nl80211: External authentication in driver-based AP SME mode
2ab19f4be Reset beacon_set_done on disabling interface
Change-Id: I5642b46d79aee83dd4f4307bf781d57b318831bd
diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
index d45ab84..de40171 100644
--- a/src/ap/ap_drv_ops.h
+++ b/src/ap/ap_drv_ops.h
@@ -364,4 +364,14 @@
return hapd->driver->channel_info(hapd->drv_priv, ci);
}
+static inline int
+hostapd_drv_send_external_auth_status(struct hostapd_data *hapd,
+ struct external_auth *params)
+{
+ if (!hapd->driver || !hapd->drv_priv ||
+ !hapd->driver->send_external_auth_status)
+ return -1;
+ return hapd->driver->send_external_auth_status(hapd->drv_priv, params);
+}
+
#endif /* AP_DRV_OPS */
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 77742f4..20c8e8f 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -352,6 +352,7 @@
return;
}
hapd->started = 0;
+ hapd->beacon_set_done = 0;
wpa_printf(MSG_DEBUG, "%s(%s)", __func__, hapd->conf->iface);
iapp_deinit(hapd->iapp);
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 28aca46..5cd2562 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -701,6 +701,21 @@
}
+static void sae_sme_send_external_auth_status(struct hostapd_data *hapd,
+ struct sta_info *sta, u16 status)
+{
+ struct external_auth params;
+
+ os_memset(¶ms, 0, sizeof(params));
+ params.status = status;
+ params.bssid = sta->addr;
+ if (status == WLAN_STATUS_SUCCESS && sta->sae)
+ params.pmkid = sta->sae->pmkid;
+
+ hostapd_drv_send_external_auth_status(hapd, ¶ms);
+}
+
+
void sae_accept_sta(struct hostapd_data *hapd, struct sta_info *sta)
{
#ifndef CONFIG_NO_VLAN
@@ -739,14 +754,18 @@
sae_set_state(sta, SAE_ACCEPTED, "Accept Confirm");
wpa_auth_pmksa_add_sae(hapd->wpa_auth, sta->addr,
sta->sae->pmk, sta->sae->pmkid);
+ sae_sme_send_external_auth_status(hapd, sta, WLAN_STATUS_SUCCESS);
}
static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
- const u8 *bssid, u8 auth_transaction, int allow_reuse)
+ const u8 *bssid, u8 auth_transaction, int allow_reuse,
+ int *sta_removed)
{
int ret;
+ *sta_removed = 0;
+
if (auth_transaction != 1 && auth_transaction != 2)
return WLAN_STATUS_UNSPECIFIED_FAILURE;
@@ -847,7 +866,7 @@
* additional events.
*/
return sae_sm_step(hapd, sta, bssid, auth_transaction,
- 0);
+ 0, sta_removed);
}
break;
case SAE_CONFIRMED:
@@ -880,8 +899,9 @@
wpa_printf(MSG_DEBUG, "SAE: remove the STA (" MACSTR
") doing reauthentication",
MAC2STR(sta->addr));
- ap_free_sta(hapd, sta);
wpa_auth_pmksa_remove(hapd->wpa_auth, sta->addr);
+ ap_free_sta(hapd, sta);
+ *sta_removed = 1;
} else if (auth_transaction == 1) {
wpa_printf(MSG_DEBUG, "SAE: Start reauthentication");
ret = auth_sae_send_commit(hapd, sta, bssid, 1);
@@ -963,6 +983,7 @@
int *groups = hapd->conf->sae_groups;
int default_groups[] = { 19, 0 };
const u8 *pos, *end;
+ int sta_removed = 0;
if (!groups)
groups = default_groups;
@@ -1157,7 +1178,7 @@
}
resp = sae_sm_step(hapd, sta, mgmt->bssid, auth_transaction,
- allow_reuse);
+ allow_reuse, &sta_removed);
} else if (auth_transaction == 2) {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
@@ -1198,7 +1219,8 @@
}
sta->sae->rc = peer_send_confirm;
}
- resp = sae_sm_step(hapd, sta, mgmt->bssid, auth_transaction, 0);
+ resp = sae_sm_step(hapd, sta, mgmt->bssid, auth_transaction, 0,
+ &sta_removed);
} else {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
@@ -1210,7 +1232,7 @@
}
reply:
- if (resp != WLAN_STATUS_SUCCESS) {
+ if (!sta_removed && resp != WLAN_STATUS_SUCCESS) {
pos = mgmt->u.auth.variable;
end = ((const u8 *) mgmt) + len;
@@ -1220,6 +1242,7 @@
!data && end - pos >= 2)
data = wpabuf_alloc_copy(pos, 2);
+ sae_sme_send_external_auth_status(hapd, sta, resp);
send_auth_reply(hapd, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
auth_transaction, resp,
data ? wpabuf_head(data) : (u8 *) "",
@@ -1227,8 +1250,9 @@
}
remove_sta:
- if (sta->added_unassoc && (resp != WLAN_STATUS_SUCCESS ||
- status_code != WLAN_STATUS_SUCCESS)) {
+ if (!sta_removed && sta->added_unassoc &&
+ (resp != WLAN_STATUS_SUCCESS ||
+ status_code != WLAN_STATUS_SUCCESS)) {
hostapd_drv_sta_remove(hapd, sta->addr);
sta->added_unassoc = 0;
}
diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h
index a28ddbd..12109ce 100644
--- a/src/crypto/crypto.h
+++ b/src/crypto/crypto.h
@@ -704,14 +704,6 @@
void crypto_ec_deinit(struct crypto_ec *e);
/**
- * crypto_ec_cofactor - Set the cofactor into the big number
- * @e: EC context from crypto_ec_init()
- * @cofactor: Cofactor of curve.
- * Returns: 0 on success, -1 on failure
- */
-int crypto_ec_cofactor(struct crypto_ec *e, struct crypto_bignum *cofactor);
-
-/**
* crypto_ec_prime_len - Get length of the prime in octets
* @e: EC context from crypto_ec_init()
* Returns: Length of the prime defining the group
diff --git a/src/crypto/crypto_internal.c b/src/crypto/crypto_internal.c
index d391f48..aad40af 100644
--- a/src/crypto/crypto_internal.c
+++ b/src/crypto/crypto_internal.c
@@ -310,6 +310,9 @@
os_free(ctx);
+ if (TEST_FAIL())
+ return -1;
+
return 0;
}
diff --git a/src/crypto/crypto_libtomcrypt.c b/src/crypto/crypto_libtomcrypt.c
index 980fa42..ed30efa 100644
--- a/src/crypto/crypto_libtomcrypt.c
+++ b/src/crypto/crypto_libtomcrypt.c
@@ -278,6 +278,9 @@
os_free(ctx);
+ if (TEST_FAIL())
+ return -1;
+
return ret;
}
diff --git a/src/crypto/crypto_linux.c b/src/crypto/crypto_linux.c
index 8099193..1724456 100644
--- a/src/crypto/crypto_linux.c
+++ b/src/crypto/crypto_linux.c
@@ -386,6 +386,9 @@
}
crypto_hash_deinit(ctx);
+
+ if (TEST_FAIL())
+ return -1;
return 0;
}
diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c
index 0f52101..1b0c1ec 100644
--- a/src/crypto/crypto_openssl.c
+++ b/src/crypto/crypto_openssl.c
@@ -1054,6 +1054,9 @@
HMAC_CTX_free(ctx->ctx);
bin_clear_free(ctx, sizeof(*ctx));
+ if (TEST_FAIL())
+ return -1;
+
if (res == 1) {
*len = mdlen;
return 0;
@@ -1317,6 +1320,8 @@
int crypto_bignum_rand(struct crypto_bignum *r, const struct crypto_bignum *m)
{
+ if (TEST_FAIL())
+ return -1;
return BN_rand_range((BIGNUM *) r, (const BIGNUM *) m) == 1 ? 0 : -1;
}
@@ -1631,13 +1636,6 @@
}
-int crypto_ec_cofactor(struct crypto_ec *e, struct crypto_bignum *cofactor)
-{
- return EC_GROUP_get_cofactor(e->group, (BIGNUM *) cofactor,
- e->bnctx) == 0 ? -1 : 0;
-}
-
-
struct crypto_ec_point * crypto_ec_point_init(struct crypto_ec *e)
{
if (TEST_FAIL())
diff --git a/src/crypto/crypto_wolfssl.c b/src/crypto/crypto_wolfssl.c
index 10cdae6..976a008 100644
--- a/src/crypto/crypto_wolfssl.c
+++ b/src/crypto/crypto_wolfssl.c
@@ -953,6 +953,8 @@
ret = 0;
done:
bin_clear_free(ctx, sizeof(*ctx));
+ if (TEST_FAIL())
+ return -1;
return ret;
}
@@ -1083,6 +1085,8 @@
int ret = 0;
WC_RNG rng;
+ if (TEST_FAIL())
+ return -1;
if (wc_InitRng(&rng) != 0)
return -1;
if (mp_rand_prime((mp_int *) r,
@@ -1348,16 +1352,6 @@
}
-int crypto_ec_cofactor(struct crypto_ec *e, struct crypto_bignum *cofactor)
-{
- if (!e || !cofactor)
- return -1;
-
- mp_set((mp_int *) cofactor, e->key.dp->cofactor);
- return 0;
-}
-
-
struct crypto_ec_point * crypto_ec_point_init(struct crypto_ec *e)
{
if (TEST_FAIL())
diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c
index 7fde21c..620254a 100644
--- a/src/crypto/tls_openssl.c
+++ b/src/crypto/tls_openssl.c
@@ -5055,6 +5055,9 @@
return -1;
#else /* OPENSSL_IS_BORINGSSL || < 1.0.2 */
#ifndef OPENSSL_NO_EC
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+ SSL_CTX_set_ecdh_auto(ssl_ctx, 1);
+#endif
if (SSL_CTX_set1_curves_list(ssl_ctx,
params->openssl_ecdh_curves) !=
1) {
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 23423d9..e7c8f31 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -2156,17 +2156,19 @@
* use %WLAN_STATUS_UNSPECIFIED_FAILURE if wpa_supplicant cannot give
* the real status code for failures. Used only for the request interface
* from user space to the driver.
+ * @pmkid: Generated PMKID as part of external auth exchange (e.g., SAE).
*/
struct external_auth {
enum {
EXT_AUTH_START,
EXT_AUTH_ABORT,
} action;
- u8 bssid[ETH_ALEN];
- u8 ssid[SSID_MAX_LEN];
+ const u8 *bssid;
+ const u8 *ssid;
size_t ssid_len;
unsigned int key_mgmt_suite;
u16 status;
+ const u8 *pmkid;
};
/**
diff --git a/src/drivers/driver_bsd.c b/src/drivers/driver_bsd.c
index 8621aa0..4675496 100644
--- a/src/drivers/driver_bsd.c
+++ b/src/drivers/driver_bsd.c
@@ -143,7 +143,7 @@
ireq->i_data = arg;
if (ioctl(drv->global->sock, SIOCG80211, ireq) < 0) {
- wpa_printf(MSG_ERROR, "ioctl[SIOCS80211, op=%u, "
+ wpa_printf(MSG_ERROR, "ioctl[SIOCG80211, op=%u, "
"arg_len=%u]: %s", op, arg_len, strerror(errno));
return -1;
}
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 661e34e..21d1398 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -307,6 +307,7 @@
os_memcpy(drv->prev_bssid, drv->bssid, ETH_ALEN);
drv->associated = 0;
os_memset(drv->bssid, 0, ETH_ALEN);
+ drv->first_bss->freq = 0;
}
@@ -2469,6 +2470,16 @@
if (nl80211_action_subscribe_ap(bss))
goto out_err;
+ if (bss->drv->device_ap_sme) {
+ u16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_AUTH << 4);
+
+ /* Register for all Authentication frames */
+ if (nl80211_register_frame(bss, bss->nl_mgmt, type, NULL, 0)
+ < 0)
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Failed to subscribe to handle Authentication frames - SAE offload may not work");
+ }
+
nl80211_mgmt_handle_register_eloop(bss);
return 0;
@@ -4160,6 +4171,9 @@
nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT)))
goto fail;
+ if (drv->device_ap_sme && (params->key_mgmt_suites & WPA_KEY_MGMT_SAE))
+ nla_put_flag(msg, NL80211_ATTR_EXTERNAL_AUTH_SUPPORT);
+
wpa_printf(MSG_DEBUG, "nl80211: pairwise_ciphers=0x%x",
params->pairwise_ciphers);
num_suites = wpa_cipher_to_cipher_suites(params->pairwise_ciphers,
@@ -8272,6 +8286,7 @@
struct i802_bss *bss = priv;
struct wpa_driver_nl80211_data *drv = bss->drv;
struct nl_msg *msg;
+ u64 cookie;
int ret;
if (!drv->poll_command_supported) {
@@ -8285,11 +8300,16 @@
return;
}
- ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+ ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie);
if (ret < 0) {
wpa_printf(MSG_DEBUG, "nl80211: Client probe request for "
MACSTR " failed: ret=%d (%s)",
MAC2STR(addr), ret, strerror(-ret));
+ } else {
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Client probe request addr=" MACSTR
+ " cookie=%llu", MAC2STR(addr),
+ (long long unsigned int) cookie);
}
}
@@ -10792,15 +10812,27 @@
struct nl_msg *msg = NULL;
int ret = -1;
+ /* External auth command/status is intended for drivers that implement
+ * intenral SME but want to offload authentication processing (e.g.,
+ * SAE) to hostapd/wpa_supplicant. Do nott send the status to drivers
+ * which do not support AP SME or use wpa_supplicant/hostapd SME.
+ */
+ if (!bss->drv->device_ap_sme ||
+ (drv->capa.flags & WPA_DRIVER_FLAGS_SME))
+ return -1;
+
wpa_dbg(drv->ctx, MSG_DEBUG,
"nl80211: External auth status: %u", params->status);
msg = nl80211_drv_msg(drv, 0, NL80211_CMD_EXTERNAL_AUTH);
if (!msg ||
nla_put_u16(msg, NL80211_ATTR_STATUS_CODE, params->status) ||
- nla_put(msg, NL80211_ATTR_SSID, params->ssid_len,
- params->ssid) ||
- nla_put(msg, NL80211_ATTR_BSSID, ETH_ALEN, params->bssid))
+ (params->ssid && params->ssid_len &&
+ nla_put(msg, NL80211_ATTR_SSID, params->ssid_len, params->ssid)) ||
+ (params->pmkid &&
+ nla_put(msg, NL80211_ATTR_PMKID, PMKID_LEN, params->pmkid)) ||
+ (params->bssid &&
+ nla_put(msg, NL80211_ATTR_BSSID, ETH_ALEN, params->bssid)))
goto fail;
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
msg = NULL;
diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
index ffddd94..ee7b4da 100644
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -267,8 +267,6 @@
event.assoc_info.req_ies_len = nla_len(req_ie);
}
- event.assoc_info.freq = drv->assoc_freq;
-
/* When this association was initiated outside of wpa_supplicant,
* drv->ssid needs to be set here to satisfy later checking. */
ssid_len = nl80211_get_assoc_ssid(drv, drv->ssid);
@@ -279,6 +277,9 @@
wpa_ssid_txt(drv->ssid, drv->ssid_len));
}
+ event.assoc_info.freq = drv->assoc_freq;
+ drv->first_bss->freq = drv->assoc_freq;
+
nl80211_parse_wmm_params(wmm, &event.assoc_info.wmm_params);
wpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event);
@@ -408,6 +409,7 @@
}
event.assoc_info.freq = nl80211_get_assoc_freq(drv);
+ drv->first_bss->freq = drv->assoc_freq;
if ((!ssid || ssid[1] == 0 || ssid[1] > 32) &&
(ssid_len = nl80211_get_assoc_ssid(drv, drv->ssid)) > 0) {
@@ -1436,16 +1438,23 @@
struct nlattr **tb)
{
union wpa_event_data data;
+ const u8 *addr;
+ u64 cookie = 0;
- wpa_printf(MSG_DEBUG, "nl80211: Probe client event");
-
- if (!tb[NL80211_ATTR_MAC] || !tb[NL80211_ATTR_ACK])
+ addr = nla_data(tb[NL80211_ATTR_MAC]);
+ if (!addr)
+ return;
+ if (tb[NL80211_ATTR_COOKIE])
+ cookie = nla_get_u64(tb[NL80211_ATTR_COOKIE]);
+ wpa_printf(MSG_DEBUG, "nl80211: Probe client event (addr=" MACSTR
+ " ack=%d cookie=%llu)", MAC2STR(addr),
+ tb[NL80211_ATTR_ACK] != NULL,
+ (long long unsigned int) cookie);
+ if (!tb[NL80211_ATTR_ACK])
return;
os_memset(&data, 0, sizeof(data));
- os_memcpy(data.client_poll.addr,
- nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);
-
+ os_memcpy(data.client_poll.addr, addr, ETH_ALEN);
wpa_supplicant_event(drv->ctx, EVENT_DRIVER_CLIENT_POLL_OK, &data);
}
@@ -2269,11 +2278,9 @@
event.external_auth.ssid_len = nla_len(tb[NL80211_ATTR_SSID]);
if (event.external_auth.ssid_len > SSID_MAX_LEN)
return;
- os_memcpy(event.external_auth.ssid, nla_data(tb[NL80211_ATTR_SSID]),
- event.external_auth.ssid_len);
+ event.external_auth.ssid = nla_data(tb[NL80211_ATTR_SSID]);
- os_memcpy(event.external_auth.bssid, nla_data(tb[NL80211_ATTR_BSSID]),
- ETH_ALEN);
+ event.external_auth.bssid = nla_data(tb[NL80211_ATTR_BSSID]);
wpa_printf(MSG_DEBUG,
"nl80211: External auth action: %u, AKM: 0x%x",
diff --git a/src/eap_common/eap_pwd_common.c b/src/eap_common/eap_pwd_common.c
index 4288b52..884150e 100644
--- a/src/eap_common/eap_pwd_common.c
+++ b/src/eap_common/eap_pwd_common.c
@@ -85,10 +85,23 @@
}
+static int eap_pwd_suitable_group(u16 num)
+{
+ /* Do not allow ECC groups with prime under 256 bits based on guidance
+ * for the similar design in SAE. */
+ return num == 19 || num == 20 || num == 21 ||
+ num == 28 || num == 29 || num == 30;
+}
+
+
EAP_PWD_group * get_eap_pwd_group(u16 num)
{
EAP_PWD_group *grp;
+ if (!eap_pwd_suitable_group(num)) {
+ wpa_printf(MSG_INFO, "EAP-pwd: unsuitable group %u", num);
+ return NULL;
+ }
grp = os_zalloc(sizeof(EAP_PWD_group));
if (!grp)
return NULL;
@@ -138,7 +151,7 @@
u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_*
* mask */
size_t primebytelen = 0, primebitlen;
- struct crypto_bignum *x_candidate = NULL, *cofactor = NULL;
+ struct crypto_bignum *x_candidate = NULL;
const struct crypto_bignum *prime;
u8 mask, found_ctr = 0, is_odd = 0;
@@ -148,21 +161,15 @@
os_memset(x_bin, 0, sizeof(x_bin));
prime = crypto_ec_get_prime(grp->group);
- cofactor = crypto_bignum_init();
grp->pwe = crypto_ec_point_init(grp->group);
tmp1 = crypto_bignum_init();
pm1 = crypto_bignum_init();
one = crypto_bignum_init_set((const u8 *) "\x01", 1);
- if (!cofactor || !grp->pwe || !tmp1 || !pm1 || !one) {
+ if (!grp->pwe || !tmp1 || !pm1 || !one) {
wpa_printf(MSG_INFO, "EAP-pwd: unable to create bignums");
goto fail;
}
- if (crypto_ec_cofactor(grp->group, cofactor) < 0) {
- wpa_printf(MSG_INFO, "EAP-pwd: unable to get cofactor for "
- "curve");
- goto fail;
- }
primebitlen = crypto_ec_prime_len_bits(grp->group);
primebytelen = crypto_ec_prime_len(grp->group);
if ((prfbuf = os_malloc(primebytelen)) == NULL) {
@@ -327,19 +334,6 @@
goto fail;
}
- if (!crypto_bignum_is_one(cofactor)) {
- /* make sure the point is not in a small sub-group */
- if (crypto_ec_point_mul(grp->group, grp->pwe, cofactor,
- grp->pwe) != 0) {
- wpa_printf(MSG_INFO,
- "EAP-pwd: cannot multiply generator by order");
- goto fail;
- }
- if (crypto_ec_point_is_at_infinity(grp->group, grp->pwe)) {
- wpa_printf(MSG_INFO, "EAP-pwd: point is at infinity");
- goto fail;
- }
- }
wpa_printf(MSG_DEBUG, "EAP-pwd: found a PWE in %02d tries", found_ctr);
if (0) {
@@ -349,7 +343,6 @@
ret = 1;
}
/* cleanliness and order.... */
- crypto_bignum_deinit(cofactor, 1);
crypto_bignum_deinit(x_candidate, 1);
crypto_bignum_deinit(pm1, 0);
crypto_bignum_deinit(tmp1, 1);
@@ -451,7 +444,6 @@
struct crypto_ec_point *element;
const struct crypto_bignum *prime;
size_t prime_len;
- struct crypto_bignum *cofactor = NULL;
prime = crypto_ec_get_prime(group->group);
prime_len = crypto_ec_prime_len(group->group);
@@ -476,35 +468,7 @@
goto fail;
}
- cofactor = crypto_bignum_init();
- if (!cofactor || crypto_ec_cofactor(group->group, cofactor) < 0) {
- wpa_printf(MSG_INFO,
- "EAP-pwd: Unable to get cofactor for curve");
- goto fail;
- }
-
- if (!crypto_bignum_is_one(cofactor)) {
- struct crypto_ec_point *point;
- int ok = 1;
-
- /* check to ensure peer's element is not in a small sub-group */
- point = crypto_ec_point_init(group->group);
- if (!point ||
- crypto_ec_point_mul(group->group, element,
- cofactor, point) != 0 ||
- crypto_ec_point_is_at_infinity(group->group, point))
- ok = 0;
- crypto_ec_point_deinit(point, 0);
-
- if (!ok) {
- wpa_printf(MSG_INFO,
- "EAP-pwd: Small sub-group check on peer element failed");
- goto fail;
- }
- }
-
out:
- crypto_bignum_deinit(cofactor, 0);
return element;
fail:
crypto_ec_point_deinit(element, 0);
diff --git a/src/eap_peer/eap_mschapv2.c b/src/eap_peer/eap_mschapv2.c
index 877495c..249baec 100644
--- a/src/eap_peer/eap_mschapv2.c
+++ b/src/eap_peer/eap_mschapv2.c
@@ -856,9 +856,13 @@
/* MSK = server MS-MPPE-Recv-Key | MS-MPPE-Send-Key, i.e.,
* peer MS-MPPE-Send-Key | MS-MPPE-Recv-Key */
- get_asymetric_start_key(data->master_key, key, MSCHAPV2_KEY_LEN, 1, 0);
- get_asymetric_start_key(data->master_key, key + MSCHAPV2_KEY_LEN,
- MSCHAPV2_KEY_LEN, 0, 0);
+ if (get_asymetric_start_key(data->master_key, key, MSCHAPV2_KEY_LEN, 1,
+ 0) < 0 ||
+ get_asymetric_start_key(data->master_key, key + MSCHAPV2_KEY_LEN,
+ MSCHAPV2_KEY_LEN, 0, 0) < 0) {
+ os_free(key);
+ return NULL;
+ }
wpa_hexdump_key(MSG_DEBUG, "EAP-MSCHAPV2: Derived key",
key, key_len);
diff --git a/src/eap_peer/eap_pwd.c b/src/eap_peer/eap_pwd.c
index 4be4fcf..76fcad4 100644
--- a/src/eap_peer/eap_pwd.c
+++ b/src/eap_peer/eap_pwd.c
@@ -309,7 +309,7 @@
const u8 *payload, size_t payload_len)
{
struct crypto_ec_point *K = NULL;
- struct crypto_bignum *mask = NULL, *cofactor = NULL;
+ struct crypto_bignum *mask = NULL;
const u8 *ptr = payload;
u8 *scalar, *element;
size_t prime_len, order_len;
@@ -527,21 +527,14 @@
data->private_value = crypto_bignum_init();
data->my_element = crypto_ec_point_init(data->grp->group);
- cofactor = crypto_bignum_init();
data->my_scalar = crypto_bignum_init();
mask = crypto_bignum_init();
- if (!data->private_value || !data->my_element || !cofactor ||
+ if (!data->private_value || !data->my_element ||
!data->my_scalar || !mask) {
wpa_printf(MSG_INFO, "EAP-PWD (peer): scalar allocation fail");
goto fin;
}
- if (crypto_ec_cofactor(data->grp->group, cofactor) < 0) {
- wpa_printf(MSG_INFO, "EAP-pwd (peer): unable to get cofactor "
- "for curve");
- goto fin;
- }
-
if (eap_pwd_get_rand_mask(data->grp, data->private_value, mask,
data->my_scalar) < 0)
goto fin;
@@ -595,17 +588,8 @@
goto fin;
}
- /* ensure that the shared key isn't in a small sub-group */
- if (!crypto_bignum_is_one(cofactor)) {
- if (crypto_ec_point_mul(data->grp->group, K, cofactor, K) < 0) {
- wpa_printf(MSG_INFO, "EAP-PWD (peer): cannot multiply "
- "shared key point by order");
- goto fin;
- }
- }
-
/*
- * This check is strictly speaking just for the case above where
+ * This check is strictly speaking just for the case where
* co-factor > 1 but it was suggested that even though this is probably
* never going to happen it is a simple and safe check "just to be
* sure" so let's be safe.
@@ -644,7 +628,6 @@
fin:
crypto_bignum_deinit(mask, 1);
- crypto_bignum_deinit(cofactor, 1);
crypto_ec_point_deinit(K, 1);
if (data->outbuf == NULL)
eap_pwd_state(data, FAILURE);
@@ -949,6 +932,13 @@
* buffer and ACK the fragment
*/
if (EAP_PWD_GET_MORE_BIT(lm_exch) || data->in_frag_pos) {
+ if (!data->inbuf) {
+ wpa_printf(MSG_DEBUG,
+ "EAP-pwd: No buffer for reassembly");
+ ret->methodState = METHOD_DONE;
+ ret->decision = DECISION_FAIL;
+ return NULL;
+ }
data->in_frag_pos += len;
if (data->in_frag_pos > wpabuf_size(data->inbuf)) {
wpa_printf(MSG_INFO, "EAP-pwd: Buffer overflow attack "
@@ -975,7 +965,7 @@
/*
* we're buffering and this is the last fragment
*/
- if (data->in_frag_pos) {
+ if (data->in_frag_pos && data->inbuf) {
wpa_printf(MSG_DEBUG, "EAP-pwd: Last fragment, %d bytes",
(int) len);
pos = wpabuf_head_u8(data->inbuf);
diff --git a/src/eap_server/eap_server_mschapv2.c b/src/eap_server/eap_server_mschapv2.c
index 6c47bb6..e9e03b0 100644
--- a/src/eap_server/eap_server_mschapv2.c
+++ b/src/eap_server/eap_server_mschapv2.c
@@ -551,9 +551,13 @@
if (key == NULL)
return NULL;
/* MSK = server MS-MPPE-Recv-Key | MS-MPPE-Send-Key */
- get_asymetric_start_key(data->master_key, key, MSCHAPV2_KEY_LEN, 0, 1);
- get_asymetric_start_key(data->master_key, key + MSCHAPV2_KEY_LEN,
- MSCHAPV2_KEY_LEN, 1, 1);
+ if (get_asymetric_start_key(data->master_key, key, MSCHAPV2_KEY_LEN, 0,
+ 1) < 0 ||
+ get_asymetric_start_key(data->master_key, key + MSCHAPV2_KEY_LEN,
+ MSCHAPV2_KEY_LEN, 1, 1) < 0) {
+ os_free(key);
+ return NULL;
+ }
wpa_hexdump_key(MSG_DEBUG, "EAP-MSCHAPV2: Derived key", key, *len);
return key;
diff --git a/src/eap_server/eap_server_pwd.c b/src/eap_server/eap_server_pwd.c
index 9799c81..e720a28 100644
--- a/src/eap_server/eap_server_pwd.c
+++ b/src/eap_server/eap_server_pwd.c
@@ -311,7 +311,7 @@
static void eap_pwd_build_confirm_req(struct eap_sm *sm,
struct eap_pwd_data *data, u8 id)
{
- struct crypto_hash *hash;
+ struct crypto_hash *hash = NULL;
u8 conf[SHA256_MAC_LEN], *cruft = NULL, *ptr;
u16 grp;
size_t prime_len, order_len;
@@ -392,6 +392,7 @@
/* all done with the random function */
eap_pwd_h_final(hash, conf);
+ hash = NULL;
os_memcpy(data->my_confirm, conf, SHA256_MAC_LEN);
data->outbuf = wpabuf_alloc(SHA256_MAC_LEN);
@@ -404,6 +405,7 @@
bin_clear_free(cruft, prime_len * 2);
if (data->outbuf == NULL)
eap_pwd_state(data, FAILURE);
+ eap_pwd_h_final(hash, NULL);
}
@@ -648,7 +650,6 @@
const u8 *payload, size_t payload_len)
{
const u8 *ptr;
- struct crypto_bignum *cofactor = NULL;
struct crypto_ec_point *K = NULL;
int res = 0;
size_t prime_len, order_len;
@@ -667,20 +668,13 @@
}
data->k = crypto_bignum_init();
- cofactor = crypto_bignum_init();
K = crypto_ec_point_init(data->grp->group);
- if (!data->k || !cofactor || !K) {
+ if (!data->k || !K) {
wpa_printf(MSG_INFO, "EAP-PWD (server): peer data allocation "
"fail");
goto fin;
}
- if (crypto_ec_cofactor(data->grp->group, cofactor) < 0) {
- wpa_printf(MSG_INFO, "EAP-PWD (server): unable to get "
- "cofactor for curve");
- goto fin;
- }
-
/* element, x then y, followed by scalar */
ptr = payload;
data->peer_element = eap_pwd_get_element(data->grp, ptr);
@@ -718,18 +712,8 @@
goto fin;
}
- /* ensure that the shared key isn't in a small sub-group */
- if (!crypto_bignum_is_one(cofactor)) {
- if (crypto_ec_point_mul(data->grp->group, K, cofactor,
- K) != 0) {
- wpa_printf(MSG_INFO, "EAP-PWD (server): cannot "
- "multiply shared key point by order!\n");
- goto fin;
- }
- }
-
/*
- * This check is strictly speaking just for the case above where
+ * This check is strictly speaking just for the case where
* co-factor > 1 but it was suggested that even though this is probably
* never going to happen it is a simple and safe check "just to be
* sure" so let's be safe.
@@ -748,7 +732,6 @@
fin:
crypto_ec_point_deinit(K, 1);
- crypto_bignum_deinit(cofactor, 1);
if (res)
eap_pwd_state(data, PWD_Confirm_Req);
@@ -761,7 +744,7 @@
eap_pwd_process_confirm_resp(struct eap_sm *sm, struct eap_pwd_data *data,
const u8 *payload, size_t payload_len)
{
- struct crypto_hash *hash;
+ struct crypto_hash *hash = NULL;
u32 cs;
u16 grp;
u8 conf[SHA256_MAC_LEN], *cruft = NULL, *ptr;
@@ -836,6 +819,7 @@
/* all done */
eap_pwd_h_final(hash, conf);
+ hash = NULL;
ptr = (u8 *) payload;
if (os_memcmp_const(conf, ptr, SHA256_MAC_LEN)) {
@@ -855,6 +839,7 @@
fin:
bin_clear_free(cruft, prime_len * 2);
+ eap_pwd_h_final(hash, NULL);
}
@@ -927,6 +912,12 @@
* the first and all intermediate fragments have the M bit set
*/
if (EAP_PWD_GET_MORE_BIT(lm_exch) || data->in_frag_pos) {
+ if (!data->inbuf) {
+ wpa_printf(MSG_DEBUG,
+ "EAP-pwd: No buffer for reassembly");
+ eap_pwd_state(data, FAILURE);
+ return;
+ }
if ((data->in_frag_pos + len) > wpabuf_size(data->inbuf)) {
wpa_printf(MSG_DEBUG, "EAP-pwd: Buffer overflow "
"attack detected! (%d+%d > %d)",
@@ -947,7 +938,7 @@
* last fragment won't have the M bit set (but we're obviously
* buffering fragments so that's how we know it's the last)
*/
- if (data->in_frag_pos) {
+ if (data->in_frag_pos && data->inbuf) {
pos = wpabuf_head_u8(data->inbuf);
len = data->in_frag_pos;
wpa_printf(MSG_DEBUG, "EAP-pwd: Last fragment, %d bytes",
@@ -1047,14 +1038,6 @@
int eap_server_pwd_register(void)
{
struct eap_method *eap;
- struct timeval tp;
- struct timezone tz;
- u32 sr;
-
- sr = 0xdeaddada;
- (void) gettimeofday(&tp, &tz);
- sr ^= (tp.tv_sec ^ tp.tv_usec);
- srandom(sr);
eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_PWD,
diff --git a/src/pae/ieee802_1x_cp.c b/src/pae/ieee802_1x_cp.c
index 8cdce30..1c4dc3e 100644
--- a/src/pae/ieee802_1x_cp.c
+++ b/src/pae/ieee802_1x_cp.c
@@ -214,6 +214,10 @@
SM_ENTRY(CP, RECEIVE);
/* RECEIVE state machine not keep with Figure 12-2 in
* IEEE Std 802.1X-2010 */
+ if (sm->oki) {
+ ieee802_1x_kay_delete_sas(sm->kay, sm->oki);
+ os_free(sm->oki);
+ }
sm->oki = sm->lki;
sm->oan = sm->lan;
sm->otx = sm->ltx;
diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index a7adbad..66a8643 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -1021,8 +1021,6 @@
}
os_memset(&gd, 0, sizeof(gd));
- wpa_supplicant_key_neg_complete(sm, sm->bssid,
- key_info & WPA_KEY_INFO_SECURE);
return 0;
}
@@ -1060,9 +1058,27 @@
broadcast_ether_addr,
keyidx, 0, igtk->pn, sizeof(igtk->pn),
igtk->igtk, len) < 0) {
- wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
- "WPA: Failed to configure IGTK to the driver");
- return -1;
+ if (keyidx == 0x0400 || keyidx == 0x0500) {
+ /* Assume the AP has broken PMF implementation since it
+ * seems to have swapped the KeyID bytes. The AP cannot
+ * be trusted to implement BIP correctly or provide a
+ * valid IGTK, so do not try to configure this key with
+ * swapped KeyID bytes. Instead, continue without
+ * configuring the IGTK so that the driver can drop any
+ * received group-addressed robust management frames due
+ * to missing keys.
+ *
+ * Normally, this error behavior would result in us
+ * disconnecting, but there are number of deployed APs
+ * with this broken behavior, so as an interoperability
+ * workaround, allow the connection to proceed. */
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "WPA: Ignore IGTK configuration error due to invalid IGTK KeyID byte order");
+ } else {
+ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
+ "WPA: Failed to configure IGTK to the driver");
+ return -1;
+ }
}
if (wnm_sleep) {
@@ -1503,8 +1519,11 @@
wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE);
if (sm->group_cipher == WPA_CIPHER_GTK_NOT_USED) {
- wpa_supplicant_key_neg_complete(sm, sm->bssid,
- key_info & WPA_KEY_INFO_SECURE);
+ /* No GTK to be set to the driver */
+ } else if (!ie.gtk && sm->proto == WPA_PROTO_RSN) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "RSN: No GTK KDE included in EAPOL-Key msg 3/4");
+ goto failed;
} else if (ie.gtk &&
wpa_supplicant_pairwise_gtk(sm, key,
ie.gtk, ie.gtk_len, key_info) < 0) {
@@ -1519,6 +1538,10 @@
goto failed;
}
+ if (sm->group_cipher == WPA_CIPHER_GTK_NOT_USED || ie.gtk)
+ wpa_supplicant_key_neg_complete(sm, sm->bssid,
+ key_info & WPA_KEY_INFO_SECURE);
+
if (ie.gtk)
wpa_sm_set_rekey_offload(sm);