diff options
author | TreeHugger Robot <treehugger-gerrit@google.com> | 2019-04-19 20:05:50 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2019-04-19 20:05:50 +0000 |
commit | 200b74922ba9c9147812b97b8d1defe9b92049ba (patch) | |
tree | 4cbaa9a808a257f8ae3a10113a7f25c96e8a5ab9 | |
parent | 33df1fd2f293bdf6a26938c701064f94d620c92a (diff) | |
parent | 5f92bc919aede94d14fc7eae550de2a236127c19 (diff) | |
download | wpa_supplicant_8-200b74922ba9c9147812b97b8d1defe9b92049ba.tar.gz |
Merge "[wpa_supplicant] Cumulative patch from 6151c9b90" into qt-dev
30 files changed, 289 insertions, 217 deletions
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index 78e52a6f..e4b16e61 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -883,7 +883,7 @@ static int hostapd_ctrl_iface_bss_tm_req(struct hostapd_data *hapd, /* TODO: TSF configurable/learnable */ bss_term_dur[0] = 4; /* Subelement ID */ bss_term_dur[1] = 10; /* Length */ - os_memset(bss_term_dur, 2, 8); + os_memset(&bss_term_dur[2], 0, 8); end = os_strchr(pos, ','); if (end == NULL) { wpa_printf(MSG_DEBUG, "Invalid bss_term data"); diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h index d45ab846..de40171e 100644 --- a/src/ap/ap_drv_ops.h +++ b/src/ap/ap_drv_ops.h @@ -364,4 +364,14 @@ static inline int hostapd_drv_channel_info(struct hostapd_data *hapd, 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 77742f44..20c8e8f5 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -352,6 +352,7 @@ static void hostapd_free_hapd_data(struct hostapd_data *hapd) 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 28aca466..5cd25626 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -701,6 +701,21 @@ static void sae_set_retransmit_timer(struct hostapd_data *hapd, } +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 @@ void sae_accept_sta(struct hostapd_data *hapd, struct sta_info *sta) 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 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta, * additional events. */ return sae_sm_step(hapd, sta, bssid, auth_transaction, - 0); + 0, sta_removed); } break; case SAE_CONFIRMED: @@ -880,8 +899,9 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta, 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 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta, 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 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta, } 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 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta, } 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 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta, } 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 @@ reply: !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 @@ reply: } 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 a28ddbd7..12109ce8 100644 --- a/src/crypto/crypto.h +++ b/src/crypto/crypto.h @@ -704,14 +704,6 @@ struct crypto_ec * crypto_ec_init(int group); 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 d391f48a..aad40af1 100644 --- a/src/crypto/crypto_internal.c +++ b/src/crypto/crypto_internal.c @@ -310,6 +310,9 @@ int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) 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 980fa422..ed30efa0 100644 --- a/src/crypto/crypto_libtomcrypt.c +++ b/src/crypto/crypto_libtomcrypt.c @@ -278,6 +278,9 @@ int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) 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 8099193b..17244561 100644 --- a/src/crypto/crypto_linux.c +++ b/src/crypto/crypto_linux.c @@ -386,6 +386,9 @@ int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) } 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 0f52101e..1b0c1ec9 100644 --- a/src/crypto/crypto_openssl.c +++ b/src/crypto/crypto_openssl.c @@ -1054,6 +1054,9 @@ int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) 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_to_bin(const struct crypto_bignum *a, 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 @@ void crypto_ec_deinit(struct crypto_ec *e) } -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 10cdae60..976a0086 100644 --- a/src/crypto/crypto_wolfssl.c +++ b/src/crypto/crypto_wolfssl.c @@ -953,6 +953,8 @@ int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) ret = 0; done: bin_clear_free(ctx, sizeof(*ctx)); + if (TEST_FAIL()) + return -1; return ret; } @@ -1083,6 +1085,8 @@ int crypto_bignum_rand(struct crypto_bignum *r, const struct crypto_bignum *m) 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 @@ void crypto_ec_deinit(struct crypto_ec* e) } -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 7fde21cc..620254af 100644 --- a/src/crypto/tls_openssl.c +++ b/src/crypto/tls_openssl.c @@ -5055,6 +5055,9 @@ int tls_global_set_params(void *tls_ctx, 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 23423d92..e7c8f318 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -2156,17 +2156,19 @@ enum wpa_drv_update_connect_params_mask { * 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 8621aa0b..46754968 100644 --- a/src/drivers/driver_bsd.c +++ b/src/drivers/driver_bsd.c @@ -143,7 +143,7 @@ bsd_get80211(void *priv, struct ieee80211req *ireq, int op, void *arg, 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 661e34e6..21d1398e 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -307,6 +307,7 @@ void nl80211_mark_disconnected(struct wpa_driver_nl80211_data *drv) 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 @@ static int nl80211_mgmt_subscribe_ap_dev_sme(struct i802_bss *bss) 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 @@ static int wpa_driver_nl80211_set_ap(void *priv, 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 @@ static void nl80211_poll_client(void *priv, const u8 *own_addr, const u8 *addr, 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 @@ static void nl80211_poll_client(void *priv, const u8 *own_addr, const u8 *addr, 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 @@ static int nl80211_send_external_auth_status(void *priv, 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 ffddd94d..ee7b4da3 100644 --- a/src/drivers/driver_nl80211_event.c +++ b/src/drivers/driver_nl80211_event.c @@ -267,8 +267,6 @@ static void mlme_event_assoc(struct wpa_driver_nl80211_data *drv, 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 @@ static void mlme_event_assoc(struct wpa_driver_nl80211_data *drv, 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 @@ static void mlme_event_connect(struct wpa_driver_nl80211_data *drv, } 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 @@ static void nl80211_client_probe_event(struct wpa_driver_nl80211_data *drv, 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 @@ static void nl80211_external_auth(struct wpa_driver_nl80211_data *drv, 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 4288b529..884150e6 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_kdf(const u8 *key, size_t keylen, const u8 *label, } +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 @@ int compute_password_element(EAP_PWD_group *grp, u16 num, 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 @@ int compute_password_element(EAP_PWD_group *grp, u16 num, 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 @@ int compute_password_element(EAP_PWD_group *grp, u16 num, 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 @@ int compute_password_element(EAP_PWD_group *grp, u16 num, 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 * eap_pwd_get_element(EAP_PWD_group *group, 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 @@ struct crypto_ec_point * eap_pwd_get_element(EAP_PWD_group *group, 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 877495cf..249baec8 100644 --- a/src/eap_peer/eap_mschapv2.c +++ b/src/eap_peer/eap_mschapv2.c @@ -856,9 +856,13 @@ static u8 * eap_mschapv2_getKey(struct eap_sm *sm, void *priv, size_t *len) /* 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 4be4fcf3..76fcad4a 100644 --- a/src/eap_peer/eap_pwd.c +++ b/src/eap_peer/eap_pwd.c @@ -309,7 +309,7 @@ eap_pwd_perform_commit_exchange(struct eap_sm *sm, struct eap_pwd_data *data, 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 @@ eap_pwd_perform_commit_exchange(struct eap_sm *sm, struct eap_pwd_data *data, 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 @@ eap_pwd_perform_commit_exchange(struct eap_sm *sm, struct eap_pwd_data *data, 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 @@ eap_pwd_perform_commit_exchange(struct eap_sm *sm, struct eap_pwd_data *data, 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 @@ eap_pwd_process(struct eap_sm *sm, void *priv, struct eap_method_ret *ret, * 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 @@ eap_pwd_process(struct eap_sm *sm, void *priv, struct eap_method_ret *ret, /* * 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 6c47bb63..e9e03b0a 100644 --- a/src/eap_server/eap_server_mschapv2.c +++ b/src/eap_server/eap_server_mschapv2.c @@ -551,9 +551,13 @@ static u8 * eap_mschapv2_getKey(struct eap_sm *sm, void *priv, size_t *len) 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 9799c819..e720a28c 100644 --- a/src/eap_server/eap_server_pwd.c +++ b/src/eap_server/eap_server_pwd.c @@ -311,7 +311,7 @@ fin: 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 @@ static void eap_pwd_build_confirm_req(struct eap_sm *sm, /* 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 @@ fin: 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 @@ eap_pwd_process_commit_resp(struct eap_sm *sm, struct eap_pwd_data *data, 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 @@ eap_pwd_process_commit_resp(struct eap_sm *sm, struct eap_pwd_data *data, } 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 @@ eap_pwd_process_commit_resp(struct eap_sm *sm, struct eap_pwd_data *data, 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 @@ eap_pwd_process_commit_resp(struct eap_sm *sm, struct eap_pwd_data *data, 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 @@ static void 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 @@ eap_pwd_process_confirm_resp(struct eap_sm *sm, struct eap_pwd_data *data, /* 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 @@ eap_pwd_process_confirm_resp(struct eap_sm *sm, struct eap_pwd_data *data, fin: bin_clear_free(cruft, prime_len * 2); + eap_pwd_h_final(hash, NULL); } @@ -927,6 +912,12 @@ static void eap_pwd_process(struct eap_sm *sm, void *priv, * 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 @@ static void eap_pwd_process(struct eap_sm *sm, void *priv, * 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 @@ static u8 * eap_pwd_get_session_id(struct eap_sm *sm, void *priv, size_t *len) 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 8cdce30e..1c4dc3e6 100644 --- a/src/pae/ieee802_1x_cp.c +++ b/src/pae/ieee802_1x_cp.c @@ -214,6 +214,10 @@ SM_STATE(CP, RECEIVE) 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 a7adbadf..66a86430 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -1021,8 +1021,6 @@ static int wpa_supplicant_pairwise_gtk(struct wpa_sm *sm, } 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 @@ static int wpa_supplicant_install_igtk(struct wpa_sm *sm, 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 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, 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 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, 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); diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 564f32b8..198ac562 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -7715,7 +7715,7 @@ static int wpas_ctrl_iface_get_pref_freq_list( wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_PREF_FREQ_LIST iface_type=%d (%s)", - iface_type, buf); + iface_type, cmd); ret = wpa_drv_get_pref_freq_list(wpa_s, iface_type, &num, freq_list); if (ret) diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 632252cb..815b9947 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -2859,8 +2859,17 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, } wpa_supplicant_cancel_scan(wpa_s); - if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) && - wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) { + if (ft_completed) { + /* + * FT protocol completed - make sure EAPOL state machine ends + * up in authenticated. + */ + wpa_supplicant_cancel_auth_timeout(wpa_s); + wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); + eapol_sm_notify_portValid(wpa_s->eapol, TRUE); + eapol_sm_notify_eap_success(wpa_s->eapol, TRUE); + } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) && + wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) { /* * We are done; the driver will take care of RSN 4-way * handshake. @@ -2877,15 +2886,6 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, * waiting for WPA supplicant. */ eapol_sm_notify_portValid(wpa_s->eapol, TRUE); - } else if (ft_completed) { - /* - * FT protocol completed - make sure EAPOL state machine ends - * up in authenticated. - */ - wpa_supplicant_cancel_auth_timeout(wpa_s); - wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); - eapol_sm_notify_portValid(wpa_s->eapol, TRUE); - eapol_sm_notify_eap_success(wpa_s->eapol, TRUE); } wpa_s->last_eapol_matches_bssid = 0; diff --git a/wpa_supplicant/mesh_mpm.c b/wpa_supplicant/mesh_mpm.c index 44859396..9d6ab8da 100644 --- a/wpa_supplicant/mesh_mpm.c +++ b/wpa_supplicant/mesh_mpm.c @@ -189,7 +189,7 @@ static void mesh_mpm_init_link(struct wpa_supplicant *wpa_s, do { if (os_get_random((u8 *) &llid, sizeof(llid)) < 0) - continue; + llid = 0; /* continue */ } while (!llid || llid_in_use(wpa_s, llid)); sta->my_lid = llid; diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 562caad5..70b61d6a 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -4198,6 +4198,9 @@ static void wpas_p2ps_prov_complete(void *ctx, u8 status, const u8 *dev, return; } + wpa_s->global->pending_p2ps_group = 0; + wpa_s->global->pending_p2ps_group_freq = 0; + if (conncap == P2PS_SETUP_GROUP_OWNER) { /* * We need to copy the interface name. Simply saving a @@ -4208,8 +4211,10 @@ static void wpas_p2ps_prov_complete(void *ctx, u8 status, const u8 *dev, go_ifname[0] = '\0'; if (!go_wpa_s) { - wpa_s->global->pending_p2ps_group = 1; - wpa_s->global->pending_p2ps_group_freq = freq; + if (!response_done) { + wpa_s->global->pending_p2ps_group = 1; + wpa_s->global->pending_p2ps_group_freq = freq; + } if (!wpas_p2p_create_iface(wpa_s)) os_memcpy(go_ifname, wpa_s->ifname, @@ -7223,7 +7228,7 @@ void wpas_p2p_completed(struct wpa_supplicant *wpa_s) u8 go_dev_addr[ETH_ALEN]; int persistent; int freq; - u8 ip[3 * 4]; + u8 ip[3 * 4], *ip_ptr = NULL; char ip_addr[100]; if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GROUP_FORMATION) { @@ -7270,6 +7275,7 @@ void wpas_p2p_completed(struct wpa_supplicant *wpa_s) ip[8], ip[9], ip[10], ip[11]); if (os_snprintf_error(sizeof(ip_addr), res)) ip_addr[0] = '\0'; + ip_ptr = ip; } wpas_p2p_group_started(wpa_s, 0, ssid, freq, @@ -7282,7 +7288,7 @@ void wpas_p2p_completed(struct wpa_supplicant *wpa_s) wpas_p2p_store_persistent_group(wpa_s->p2pdev, ssid, go_dev_addr); - wpas_notify_p2p_group_started(wpa_s, ssid, persistent, 1, ip); + wpas_notify_p2p_group_started(wpa_s, ssid, persistent, 1, ip_ptr); } diff --git a/wpa_supplicant/rrm.c b/wpa_supplicant/rrm.c index ab5e6dbd..cb3c6c99 100644 --- a/wpa_supplicant/rrm.c +++ b/wpa_supplicant/rrm.c @@ -397,7 +397,10 @@ static int wpas_rrm_beacon_rep_update_last_frame(u8 *pos, size_t len) struct rrm_measurement_report_element *msr_rep; u8 *end = pos + len; u8 *msr_rep_end; + struct rrm_measurement_beacon_report *rep = NULL; + u8 *subelem; + /* Find the last beacon report element */ while (end - pos >= (int) sizeof(*msr_rep)) { msr_rep = (struct rrm_measurement_report_element *) pos; msr_rep_end = pos + msr_rep->len + 2; @@ -410,30 +413,27 @@ static int wpas_rrm_beacon_rep_update_last_frame(u8 *pos, size_t len) return -1; } - if (msr_rep->type == MEASURE_TYPE_BEACON) { - struct rrm_measurement_beacon_report *rep; - u8 *subelem; - + if (msr_rep->type == MEASURE_TYPE_BEACON) rep = (struct rrm_measurement_beacon_report *) msr_rep->variable; - subelem = rep->variable; - while (subelem + 2 < msr_rep_end && - subelem[0] != - WLAN_BEACON_REPORT_SUBELEM_LAST_INDICATION) - subelem += 2 + subelem[1]; - - if (subelem + 2 < msr_rep_end && - subelem[0] == - WLAN_BEACON_REPORT_SUBELEM_LAST_INDICATION && - subelem[1] == 1 && - subelem + - BEACON_REPORT_LAST_INDICATION_SUBELEM_LEN <= end) - subelem[2] = 1; - } pos += pos[1] + 2; } + if (!rep) + return 0; + + subelem = rep->variable; + while (subelem + 2 < msr_rep_end && + subelem[0] != WLAN_BEACON_REPORT_SUBELEM_LAST_INDICATION) + subelem += 2 + subelem[1]; + + if (subelem + 2 < msr_rep_end && + subelem[0] == WLAN_BEACON_REPORT_SUBELEM_LAST_INDICATION && + subelem[1] == 1 && + subelem + BEACON_REPORT_LAST_INDICATION_SUBELEM_LEN <= end) + subelem[2] = 1; + return 0; } diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index 4bb5f3ae..17a984d1 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -965,10 +965,9 @@ static void sme_send_external_auth_status(struct wpa_supplicant *wpa_s, os_memset(¶ms, 0, sizeof(params)); params.status = status; - os_memcpy(params.ssid, wpa_s->sme.ext_auth.ssid, - wpa_s->sme.ext_auth.ssid_len); + params.ssid = wpa_s->sme.ext_auth.ssid; params.ssid_len = wpa_s->sme.ext_auth.ssid_len; - os_memcpy(params.bssid, wpa_s->sme.ext_auth.bssid, ETH_ALEN); + params.bssid = wpa_s->sme.ext_auth.bssid; wpa_drv_send_external_auth_status(wpa_s, ¶ms); } @@ -978,7 +977,7 @@ static void sme_handle_external_auth_start(struct wpa_supplicant *wpa_s, { struct wpa_ssid *ssid; size_t ssid_str_len = data->external_auth.ssid_len; - u8 *ssid_str = data->external_auth.ssid; + const u8 *ssid_str = data->external_auth.ssid; /* Get the SSID conf from the ssid string obtained */ for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { @@ -1986,17 +1985,14 @@ void sme_clear_on_disassoc(struct wpa_supplicant *wpa_s) if (wpa_s->sme.ft_ies || wpa_s->sme.ft_used) sme_update_ft_ies(wpa_s, NULL, NULL, 0); #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_IEEE80211W + sme_stop_sa_query(wpa_s); +#endif /* CONFIG_IEEE80211W */ } void sme_deinit(struct wpa_supplicant *wpa_s) { - os_free(wpa_s->sme.ft_ies); - wpa_s->sme.ft_ies = NULL; - wpa_s->sme.ft_ies_len = 0; -#ifdef CONFIG_IEEE80211W - sme_stop_sa_query(wpa_s); -#endif /* CONFIG_IEEE80211W */ sme_clear_on_disassoc(wpa_s); eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL); @@ -2401,6 +2397,8 @@ static void sme_start_sa_query(struct wpa_supplicant *wpa_s) static void sme_stop_sa_query(struct wpa_supplicant *wpa_s) { + if (wpa_s->sme.sa_query_trans_id) + wpa_dbg(wpa_s, MSG_DEBUG, "SME: Stop SA Query"); eloop_cancel_timeout(sme_sa_query_timer, wpa_s, NULL); os_free(wpa_s->sme.sa_query_trans_id); wpa_s->sme.sa_query_trans_id = NULL; diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 0f7b85de..be8efb4c 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -962,7 +962,7 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, wpa_supplicant_stop_bgscan(wpa_s); #endif /* CONFIG_BGSCAN */ - if (state == WPA_AUTHENTICATING) + if (state > WPA_SCANNING) wpa_supplicant_stop_autoscan(wpa_s); if (state == WPA_DISCONNECTED || state == WPA_INACTIVE) @@ -2522,6 +2522,9 @@ static u8 * wpas_populate_assoc_ies( #ifdef CONFIG_MBO const u8 *mbo_ie; #endif +#ifdef CONFIG_SAE + int sae_pmksa_cached = 0; +#endif /* CONFIG_SAE */ #ifdef CONFIG_FILS const u8 *realm, *username, *rrk; size_t realm_len, username_len, rrk_len; @@ -2559,8 +2562,12 @@ static u8 * wpas_populate_assoc_ies( #endif /* CONFIG_FILS */ if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid, ssid, try_opportunistic, - cache_id, 0) == 0) + cache_id, 0) == 0) { eapol_sm_notify_pmkid_attempt(wpa_s->eapol); +#ifdef CONFIG_SAE + sae_pmksa_cached = 1; +#endif /* CONFIG_SAE */ + } wpa_ie_len = max_wpa_ie_len; if (wpa_supplicant_set_suites(wpa_s, bss, ssid, wpa_ie, &wpa_ie_len)) { @@ -2673,6 +2680,14 @@ static u8 * wpas_populate_assoc_ies( "Overriding auth_alg selection: 0x%x", algs); } +#ifdef CONFIG_SAE + if (sae_pmksa_cached && algs == WPA_AUTH_ALG_SAE) { + wpa_dbg(wpa_s, MSG_DEBUG, + "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt"); + algs = WPA_AUTH_ALG_OPEN; + } +#endif /* CONFIG_SAE */ + #ifdef CONFIG_P2P if (wpa_s->global->p2p) { u8 *pos; diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index a66253fb..a9205f0b 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -318,6 +318,15 @@ fast_reauth=1 # of APs when using ap_scan=1 mode. #bss_max_count=200 +# BSS expiration age in seconds. A BSS will be removed from the local cache +# if it is not in use and has not been seen for this time. Default is 180. +#bss_expiration_age=180 + +# BSS expiration after number of scans. A BSS will be removed from the local +# cache if it is not seen in this number of scans. +# Default is 2. +#bss_expiration_scan_count=2 + # Automatic scan # This is an optional set of parameters for automatic scanning # within an interface in following format: |