diff --git a/components/esp_wifi/include/esp_wifi_types_generic.h b/components/esp_wifi/include/esp_wifi_types_generic.h index 682f133a7c57..b4255de57384 100644 --- a/components/esp_wifi/include/esp_wifi_types_generic.h +++ b/components/esp_wifi/include/esp_wifi_types_generic.h @@ -57,7 +57,7 @@ typedef struct { } wifi_country_t; /* Strength of authmodes */ -/* OPEN < WEP < WPA_PSK < OWE < WPA2_PSK = WPA_WPA2_PSK < WAPI_PSK < WPA3_PSK = WPA2_WPA3_PSK < WPA3_EXT_PSK = WPA3_EXT_PSK_MIXED_MODE */ +/* OPEN < WEP < WPA_PSK < OWE < WPA2_PSK = WPA_WPA2_PSK < WAPI_PSK < WPA3_PSK = WPA2_WPA3_PSK = DPP < WPA3_EXT_PSK = WPA3_EXT_PSK_MIXED_MODE */ typedef enum { WIFI_AUTH_OPEN = 0, /**< authenticate mode : open */ WIFI_AUTH_WEP, /**< authenticate mode : WEP */ @@ -73,6 +73,7 @@ typedef enum { WIFI_AUTH_WPA3_ENT_192, /**< authenticate mode : WPA3_ENT_SUITE_B_192_BIT */ WIFI_AUTH_WPA3_EXT_PSK, /**< authenticate mode : WPA3_PSK_EXT_KEY */ WIFI_AUTH_WPA3_EXT_PSK_MIXED_MODE, /**< authenticate mode: WPA3_PSK + WPA3_PSK_EXT_KEY */ + WIFI_AUTH_DPP, /**< authenticate mode : DPP */ WIFI_AUTH_MAX } wifi_auth_mode_t; diff --git a/components/esp_wifi/lib b/components/esp_wifi/lib index 62ed01cb7946..952cacbb3511 160000 --- a/components/esp_wifi/lib +++ b/components/esp_wifi/lib @@ -1 +1 @@ -Subproject commit 62ed01cb7946633ca315757edbd0e333ecf7be72 +Subproject commit 952cacbb3511df026d0753ffb141e289ffd12493 diff --git a/components/wpa_supplicant/esp_supplicant/include/esp_dpp.h b/components/wpa_supplicant/esp_supplicant/include/esp_dpp.h index 6bcd846ef3cf..787717408dac 100644 --- a/components/wpa_supplicant/esp_supplicant/include/esp_dpp.h +++ b/components/wpa_supplicant/esp_supplicant/include/esp_dpp.h @@ -10,6 +10,7 @@ #include #include "esp_err.h" +#include "esp_wifi_types.h" #ifdef __cplusplus extern "C" { @@ -32,6 +33,7 @@ typedef enum dpp_bootstrap_type { typedef enum { ESP_SUPP_DPP_URI_READY, /**< URI is ready through Bootstrapping */ ESP_SUPP_DPP_CFG_RECVD, /**< Config received via DPP Authentication */ + ESP_SUPP_DPP_PDR_RECVD, /**< Peer Discovery Response is received */ ESP_SUPP_DPP_FAIL, /**< DPP Authentication failure */ } esp_supp_dpp_event_t; @@ -62,8 +64,11 @@ esp_err_t esp_supp_dpp_init(esp_supp_dpp_event_cb_t evt_cb); * @brief De-initalize DPP Supplicant * * Frees memory from DPP Supplicant Data Structures. + * + * @return + * - ESP_OK: Success */ -void esp_supp_dpp_deinit(void); +esp_err_t esp_supp_dpp_deinit(void); /** * @brief Generates Bootstrap Information as an Enrollee. @@ -101,8 +106,12 @@ esp_err_t esp_supp_dpp_start_listen(void); * @brief Stop listening on Channels. * * Stops listening on Channels and cancels ongoing listen operation. + * + * @return + * - ESP_OK: Success + * - ESP_FAIL: Failure */ -void esp_supp_dpp_stop_listen(void); +esp_err_t esp_supp_dpp_stop_listen(void); #ifdef __cplusplus } diff --git a/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c b/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c index c5f38fa7937f..70a6717ca63d 100644 --- a/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c +++ b/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c @@ -26,7 +26,8 @@ #include "mbedtls/error.h" #include "mbedtls/oid.h" -#define ECP_PRV_DER_MAX_BYTES 29 + 3 * MBEDTLS_ECP_MAX_BYTES +#define ECP_PRV_DER_MAX_BYTES ( 29 + 3 * MBEDTLS_ECP_MAX_BYTES ) +#define ECP_PUB_DER_MAX_BYTES ( 30 + 2 * MBEDTLS_ECP_MAX_BYTES ) #ifdef CONFIG_MBEDTLS_ECDH_LEGACY_CONTEXT #define ACCESS_ECDH(S, var) S->MBEDTLS_PRIVATE(var) @@ -518,6 +519,7 @@ struct crypto_key * crypto_ec_set_pubkey_point(const struct crypto_ec_group *gro struct crypto_key *pkey = NULL; int ret; mbedtls_pk_context *key = (mbedtls_pk_context *)crypto_alloc_key(); + mbedtls_ecp_group *ecp_grp = (mbedtls_ecp_group *)group; if (!key) { wpa_printf(MSG_ERROR, "%s: memory allocation failed", __func__); @@ -538,7 +540,7 @@ struct crypto_key * crypto_ec_set_pubkey_point(const struct crypto_ec_group *gro goto fail; } - if (mbedtls_ecp_check_pubkey((mbedtls_ecp_group *)group, point) < 0) { //typecast + if (mbedtls_ecp_check_pubkey(ecp_grp, point) < 0) { // ideally should have failed in upper condition, duplicate code?? wpa_printf(MSG_ERROR, "Invalid key"); goto fail; @@ -547,8 +549,9 @@ struct crypto_key * crypto_ec_set_pubkey_point(const struct crypto_ec_group *gro if( ( ret = mbedtls_pk_setup( key, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY) ) ) != 0 ) goto fail; + mbedtls_ecp_copy(&mbedtls_pk_ec(*key)->MBEDTLS_PRIVATE(Q), point); - mbedtls_ecp_group_load(&mbedtls_pk_ec(*key)->MBEDTLS_PRIVATE(grp), MBEDTLS_ECP_DP_SECP256R1); + mbedtls_ecp_group_load(&mbedtls_pk_ec(*key)->MBEDTLS_PRIVATE(grp), ecp_grp->id); pkey = (struct crypto_key *)key; crypto_ec_point_deinit((struct crypto_ec_point *)point, 0); @@ -581,19 +584,27 @@ struct crypto_ec_point *crypto_ec_get_public_key(struct crypto_key *key) int crypto_ec_get_priv_key_der(struct crypto_key *key, unsigned char **key_data, int *key_len) { mbedtls_pk_context *pkey = (mbedtls_pk_context *)key; - char der_data[ECP_PRV_DER_MAX_BYTES]; + char *der_data = os_malloc(ECP_PRV_DER_MAX_BYTES); + if (!der_data) { + wpa_printf(MSG_ERROR, "memory allocation failed"); + return -1; + } *key_len = mbedtls_pk_write_key_der(pkey, (unsigned char *)der_data, ECP_PRV_DER_MAX_BYTES); - if (*key_len <= 0) + if (*key_len <= 0) { + wpa_printf(MSG_ERROR, "Failed to write priv key"); + os_free(der_data); return -1; - + } *key_data = os_malloc(*key_len); if (!*key_data) { wpa_printf(MSG_ERROR, "memory allocation failed"); + os_free(der_data); return -1; } - os_memcpy(*key_data, der_data, *key_len); + os_memcpy(*key_data, der_data + ECP_PRV_DER_MAX_BYTES - *key_len, *key_len); + os_free(der_data); return 0; } @@ -643,16 +654,25 @@ int crypto_ec_get_publickey_buf(struct crypto_key *key, u8 *key_buf, int len) int crypto_write_pubkey_der(struct crypto_key *key, unsigned char **key_buf) { - unsigned char output_buf[1600] = {0}; - int len = mbedtls_pk_write_pubkey_der((mbedtls_pk_context *)key, output_buf, 1600); - if (len <= 0) - return 0; + unsigned char *buf = os_malloc(ECP_PUB_DER_MAX_BYTES); + + if(!buf) { + wpa_printf(MSG_ERROR, "memory allocation failed"); + return -1; + } + int len = mbedtls_pk_write_pubkey_der((mbedtls_pk_context *)key, buf, ECP_PUB_DER_MAX_BYTES); + if (len <= 0) { + os_free(buf); + return -1; + } *key_buf = os_malloc(len); if (!*key_buf) { - return 0; + os_free(buf); + return -1; } - os_memcpy(*key_buf, output_buf + 1600 - len, len); + os_memcpy(*key_buf, buf + ECP_PUB_DER_MAX_BYTES - len, len); + os_free(buf); return len; } @@ -812,28 +832,21 @@ int crypto_ecdsa_get_sign(unsigned char *hash, int crypto_edcsa_sign_verify(const unsigned char *hash, const struct crypto_bignum *r, const struct crypto_bignum *s, struct crypto_key *csign, int hlen) { - mbedtls_pk_context *pkey = (mbedtls_pk_context *)csign; - int ret = 0; - - mbedtls_ecdsa_context *ctx = os_malloc(sizeof(*ctx)); - if (!ctx) { - wpa_printf(MSG_ERROR, "failed to allcate memory"); - return ret; + /* (mbedtls_ecdsa_context *) */ + mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)csign); + if (!ecp_kp) { + return -1; } - mbedtls_ecdsa_init(ctx); - - if (mbedtls_ecdsa_from_keypair(ctx, mbedtls_pk_ec(*pkey)) < 0) - return ret; - if((ret = mbedtls_ecdsa_verify(&ctx->MBEDTLS_PRIVATE(grp), hash, hlen, - &ctx->MBEDTLS_PRIVATE(Q), (mbedtls_mpi *)r, (mbedtls_mpi *)s)) != 0){ + mbedtls_ecp_group *ecp_kp_grp = &ecp_kp->MBEDTLS_PRIVATE(grp); + mbedtls_ecp_point *ecp_kp_q = &ecp_kp->MBEDTLS_PRIVATE(Q); + int ret = mbedtls_ecdsa_verify(ecp_kp_grp, hash, hlen, + ecp_kp_q, (mbedtls_mpi *)r, (mbedtls_mpi *)s); + if (ret != 0) { wpa_printf(MSG_ERROR, "ecdsa verification failed"); return ret; } - mbedtls_ecdsa_free(ctx); - os_free(ctx); - return ret; } @@ -861,14 +874,18 @@ struct crypto_key *crypto_ec_parse_subpub_key(const unsigned char *p, size_t len { int ret; mbedtls_pk_context *pkey = (mbedtls_pk_context *)crypto_alloc_key(); - ret = mbedtls_pk_parse_subpubkey((unsigned char **)&p, p + len, pkey); - if (ret < 0) { - os_free(pkey); + if (!pkey) { return NULL; } + ret = mbedtls_pk_parse_subpubkey((unsigned char **)&p, p + len, pkey); + if (ret == 0) { + return (struct crypto_key *)pkey; + } - return (struct crypto_key *)pkey; + mbedtls_pk_free(pkey); + os_free(pkey); + return NULL; } int crypto_is_ec_key(struct crypto_key *key) diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_dpp.c b/components/wpa_supplicant/esp_supplicant/src/esp_dpp.c index 83ef62caa224..6ade2addafe0 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_dpp.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_dpp.c @@ -16,6 +16,8 @@ #include "esp_wifi.h" #include "common/ieee802_11_defs.h" #include "esp_wps_i.h" +#include "rsn_supp/wpa.h" +#include "rsn_supp/pmksa_cache.h" #ifdef CONFIG_DPP static void *s_dpp_task_hdl = NULL; @@ -37,11 +39,10 @@ struct action_rx_param { struct ieee80211_action *action_frm; }; - -static int esp_dpp_post_evt(uint32_t evt_id, uint32_t data) +esp_err_t esp_dpp_post_evt(uint32_t evt_id, uint32_t data) { dpp_event_t *evt = os_zalloc(sizeof(dpp_event_t)); - int ret = ESP_OK; + esp_err_t ret = ESP_OK; if (evt == NULL) { ret = ESP_ERR_NO_MEM; @@ -95,12 +96,12 @@ static void esp_dpp_auth_conf_wait_timeout(void *eloop_ctx, void *timeout_ctx) esp_dpp_call_cb(ESP_SUPP_DPP_FAIL, (void *)ESP_ERR_DPP_AUTH_TIMEOUT); } -void esp_send_action_frame(uint8_t *dest_mac, const uint8_t *buf, uint32_t len, +esp_err_t esp_dpp_send_action_frame(uint8_t *dest_mac, const uint8_t *buf, uint32_t len, uint8_t channel, uint32_t wait_time_ms) { wifi_action_tx_req_t *req = os_zalloc(sizeof(*req) + len);; if (!req) { - return; + return ESP_FAIL; } req->ifx = WIFI_IF_STA; @@ -115,13 +116,14 @@ void esp_send_action_frame(uint8_t *dest_mac, const uint8_t *buf, uint32_t len, if (ESP_OK != esp_wifi_action_tx_req(WIFI_OFFCHAN_TX_REQ, channel, wait_time_ms, req)) { - wpa_printf(MSG_ERROR, "DPP: Failed to perfrm offchannel operation"); + wpa_printf(MSG_ERROR, "DPP: Failed to perform offchannel operation"); esp_dpp_call_cb(ESP_SUPP_DPP_FAIL, (void *)ESP_ERR_DPP_TX_FAILURE); os_free(req); - return; + return ESP_FAIL; } os_free(req); + return ESP_OK; } static void esp_dpp_rx_auth_req(struct action_rx_param *rx_param, uint8_t *dpp_data) @@ -168,7 +170,8 @@ static void esp_dpp_rx_auth_req(struct action_rx_param *rx_param, uint8_t *dpp_d own_bi, rx_param->channel, (const u8 *)&rx_param->action_frm->u.public_action.v, dpp_data, len); os_memcpy(s_dpp_ctx.dpp_auth->peer_mac_addr, rx_param->sa, ETH_ALEN); - esp_send_action_frame(rx_param->sa, wpabuf_head(s_dpp_ctx.dpp_auth->resp_msg), + + esp_dpp_send_action_frame(rx_param->sa, wpabuf_head(s_dpp_ctx.dpp_auth->resp_msg), wpabuf_len(s_dpp_ctx.dpp_auth->resp_msg), rx_param->channel, OFFCHAN_TX_WAIT_TIME); eloop_cancel_timeout(esp_dpp_auth_conf_wait_timeout, NULL,NULL); @@ -195,7 +198,7 @@ static void gas_query_req_tx(struct dpp_authentication *auth) wpa_printf(MSG_DEBUG, "DPP: GAS request to " MACSTR " (chan %u)", MAC2STR(auth->peer_mac_addr), auth->curr_chan); - esp_send_action_frame(auth->peer_mac_addr, wpabuf_head(buf), wpabuf_len(buf), + esp_dpp_send_action_frame(auth->peer_mac_addr, wpabuf_head(buf), wpabuf_len(buf), auth->curr_chan, OFFCHAN_TX_WAIT_TIME); } @@ -203,8 +206,8 @@ static int esp_dpp_handle_config_obj(struct dpp_authentication *auth, struct dpp_config_obj *conf) { wifi_config_t *wifi_cfg = &s_dpp_ctx.wifi_cfg; - os_memset(wifi_cfg, 0, sizeof(wifi_config_t)); + if (conf->ssid_len) { os_memcpy(wifi_cfg->sta.ssid, conf->ssid, conf->ssid_len); } @@ -276,10 +279,130 @@ static void esp_dpp_rx_auth_conf(struct action_rx_param *rx_param, uint8_t *dpp_ esp_dpp_call_cb(ESP_SUPP_DPP_FAIL, (void *)rc); } -static void esp_dpp_rx_auth(struct action_rx_param *rx_param) +static esp_err_t esp_dpp_rx_peer_disc_resp(struct action_rx_param *rx_param) +{ + struct dpp_authentication *auth = s_dpp_ctx.dpp_auth; + uint8_t *buf; + unsigned int seconds; + struct os_reltime rnow; + const uint8_t *connector, *trans_id, *status = NULL; + uint16_t connector_len, trans_id_len, status_len; + enum dpp_status_error res = 0; + struct dpp_introduction intro; + os_time_t expiry; + struct os_time now; + struct wpa_sm *sm = get_wpa_sm(); + struct rsn_pmksa_cache_entry *entry = NULL; + int i = 0; + + if (!rx_param || !rx_param->action_frm) { + return ESP_ERR_INVALID_ARG; + } + + size_t len = rx_param->vendor_data_len - 2; + + buf = rx_param->action_frm->u.public_action.v.pa_vendor_spec.vendor_data; + + if (os_memcmp(auth->peer_mac_addr, rx_param->sa, ETH_ALEN) != 0) { + wpa_printf(MSG_DEBUG, "DPP: Not expecting Peer Discovery response from " MACSTR, MAC2STR(rx_param->sa)); + return ESP_OK; + } + + wpa_printf(MSG_DEBUG, "DPP: Peer Discovery from " MACSTR, MAC2STR(rx_param->sa)); + + for (i = 0; i < auth->num_conf_obj; i++) { + + if (!auth->conf_obj[i].connector + || !auth->net_access_key + || !auth->conf_obj[i].c_sign_key + || dpp_akm_legacy(auth->conf_obj[i].akm)) { + wpa_printf(MSG_DEBUG, "DPP: Profile not found for network introduction or akm mismatch"); + continue; + } + + trans_id = dpp_get_attr(&buf[2], len, DPP_ATTR_TRANSACTION_ID, &trans_id_len); + if (!trans_id || trans_id_len != 1) { + wpa_printf(MSG_ERROR, "DPP: Peer did not include Transaction ID"); + return ESP_FAIL; + } + if (trans_id[0] != TRANSACTION_ID) { + wpa_printf(MSG_ERROR, "DPP: Ignore frame with unexpected Transaction ID %u", trans_id[0]); + return ESP_FAIL; + } + + status = dpp_get_attr(&buf[2], len, DPP_ATTR_STATUS, &status_len); + if (!status || status_len != 1) { + wpa_printf(MSG_ERROR, "DPP: Peer did not include Status"); + return ESP_FAIL; + } + if (status[0] != DPP_STATUS_OK) { + wpa_printf(MSG_ERROR, "DPP: Peer rejected network introduction: Status %u", status[0]); + return ESP_FAIL; + } + + connector = dpp_get_attr(&buf[2], len, DPP_ATTR_CONNECTOR, &connector_len); + if (!connector) { + wpa_printf(MSG_ERROR, "DPP: Peer did not include its Connector"); + return ESP_FAIL; + } + + res = dpp_peer_intro(&intro, auth->conf_obj[i].connector, + wpabuf_head(auth->net_access_key), + wpabuf_len(auth->net_access_key), + wpabuf_head(auth->conf_obj[i].c_sign_key), + wpabuf_len(auth->conf_obj[i].c_sign_key), + connector, connector_len, &expiry); + + if (res == DPP_STATUS_OK) { + entry = os_zalloc(sizeof(*entry)); + if (!entry) + goto fail; + os_memcpy(entry->aa, rx_param->sa, ETH_ALEN); + os_memcpy(entry->pmkid, intro.pmkid, PMKID_LEN); + os_memcpy(entry->pmk, intro.pmk, intro.pmk_len); + entry->pmk_len = intro.pmk_len; + entry->akmp = WPA_KEY_MGMT_DPP; + + if (expiry) { + os_get_time(&now); + seconds = expiry - now.sec; + } else { + seconds = ESP_DPP_PMK_CACHE_DEFAULT_TIMEOUT; + } + os_get_reltime(&rnow); + entry->expiration = rnow.sec + seconds; + entry->reauth_time = rnow.sec + seconds; + entry->network_ctx = auth; + + pmksa_cache_add_entry(sm->pmksa, entry); + + wpa_printf(MSG_INFO, "peer=" MACSTR " status=%u", MAC2STR(rx_param->sa), status[0]); + break; + } + } + + if (res != DPP_STATUS_OK) { + wpa_printf(MSG_ERROR, "DPP: Network Introduction protocol resulted in failure"); + goto fail; + } + + wpa_printf(MSG_DEBUG, + "DPP: Try connection after successful network introduction"); + dpp_connect(rx_param->sa, true); + return ESP_OK; +fail: + os_memset(&intro, 0, sizeof(intro)); + if (entry != NULL) { + os_free(entry); + } + return ESP_FAIL; +} + +static esp_err_t esp_dpp_rx_frm(struct action_rx_param *rx_param) { uint8_t crypto_suit, type; uint8_t *tmp; + int ret = ESP_OK; tmp = rx_param->action_frm->u.public_action.v.pa_vendor_spec.vendor_data; crypto_suit = tmp[0]; @@ -288,17 +411,22 @@ static void esp_dpp_rx_auth(struct action_rx_param *rx_param) if (crypto_suit != 1) { wpa_printf(MSG_ERROR, "DPP: Unsupported crypto suit"); esp_dpp_call_cb(ESP_SUPP_DPP_FAIL, (void *)ESP_ERR_NOT_SUPPORTED); - return; + ret = ESP_FAIL; + } else { + switch (type) { + case DPP_PA_AUTHENTICATION_REQ: + esp_dpp_rx_auth_req(rx_param, &tmp[2]); + break; + case DPP_PA_AUTHENTICATION_CONF: + esp_dpp_rx_auth_conf(rx_param, &tmp[2]); + break; + case DPP_PA_PEER_DISCOVERY_RESP: + ret = esp_dpp_rx_peer_disc_resp(rx_param); + break; + } } - switch (type) { - case DPP_PA_AUTHENTICATION_REQ: - esp_dpp_rx_auth_req(rx_param, &tmp[2]); - break; - case DPP_PA_AUTHENTICATION_CONF: - esp_dpp_rx_auth_conf(rx_param, &tmp[2]); - break; - } + return ret; } static void gas_query_resp_rx(struct action_rx_param *rx_param) @@ -328,8 +456,14 @@ static void gas_query_resp_rx(struct action_rx_param *rx_param) esp_dpp_call_cb(ESP_SUPP_DPP_FAIL, (void *)ESP_ERR_DPP_FAILURE); } -static void esp_dpp_rx_action(struct action_rx_param *rx_param) +static esp_err_t esp_dpp_rx_action(struct action_rx_param *rx_param) { + + int ret = ESP_OK; + + if (!rx_param) + return ESP_ERR_INVALID_ARG; + if (rx_param->action_frm->category == WLAN_ACTION_PUBLIC) { struct ieee80211_public_action *public_action = &rx_param->action_frm->u.public_action; @@ -349,7 +483,7 @@ static void esp_dpp_rx_action(struct action_rx_param *rx_param) esp_supp_dpp_stop_listen(); } - esp_dpp_rx_auth(rx_param); + ret = esp_dpp_rx_frm(rx_param); } else if (public_action->action == WLAN_PA_GAS_INITIAL_RESP && public_action->v.pa_gas_resp.type == WLAN_EID_ADV_PROTO && public_action->v.pa_gas_resp.length == 8 && @@ -366,6 +500,7 @@ static void esp_dpp_rx_action(struct action_rx_param *rx_param) os_free(rx_param->action_frm); os_free(rx_param); + return ret; } static void esp_dpp_task(void *pvParameters ) @@ -438,6 +573,11 @@ static void esp_dpp_task(void *pvParameters ) } break; + case SIG_DPP_START_NET_INTRO: { + esp_dpp_start_net_intro_protocol((uint8_t*)evt->data); + } + break; + default: break; } @@ -657,10 +797,10 @@ esp_err_t esp_supp_dpp_start_listen(void) return esp_dpp_post_evt(SIG_DPP_LISTEN_NEXT_CHANNEL, 0); } -void esp_supp_dpp_stop_listen(void) +esp_err_t esp_supp_dpp_stop_listen(void) { s_dpp_listen_in_progress = false; - esp_wifi_remain_on_channel(WIFI_IF_STA, WIFI_ROC_CANCEL, 0, 0, NULL); + return esp_wifi_remain_on_channel(WIFI_IF_STA, WIFI_ROC_CANCEL, 0, 0, NULL); } bool is_dpp_enabled(void) @@ -744,7 +884,28 @@ esp_err_t esp_supp_dpp_init(esp_supp_dpp_event_cb_t cb) } return ret; } -void esp_supp_dpp_deinit(void) + +esp_err_t esp_dpp_start_net_intro_protocol(uint8_t *bssid) +{ + struct dpp_authentication *auth = s_dpp_ctx.dpp_auth; + struct wpabuf *buf; + for (int i = 0; i < auth->num_conf_obj; i++) { + os_memcpy(auth->peer_mac_addr, bssid, ETH_ALEN); + buf = dpp_build_peer_disc_req(auth, &auth->conf_obj[i]); + + if (buf) { + if (esp_dpp_send_action_frame(bssid, wpabuf_head(buf), wpabuf_len(buf), auth->curr_chan, OFFCHAN_TX_WAIT_TIME) != ESP_OK) { + wpabuf_free(buf); + return ESP_FAIL; + } + } else { + return ESP_ERR_NO_MEM; + } + } + return ESP_OK; +} + +esp_err_t esp_supp_dpp_deinit(void) { esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_ACTION_TX_STATUS, @@ -756,5 +917,6 @@ void esp_supp_dpp_deinit(void) wpa_printf(MSG_ERROR, "DPP Deinit Failed"); } } + return ESP_OK; } #endif diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_dpp_i.h b/components/wpa_supplicant/esp_supplicant/src/esp_dpp_i.h index 2e97d1aa39c5..2860f7097a09 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_dpp_i.h +++ b/components/wpa_supplicant/esp_supplicant/src/esp_dpp_i.h @@ -16,6 +16,7 @@ #include "esp_wifi_driver.h" #define DPP_TASK_STACK_SIZE (6144 + TASK_STACK_SIZE_ADD) +#define ESP_DPP_PMK_CACHE_DEFAULT_TIMEOUT 86400 * 7 /*!< 7 days */ enum SIG_DPP { SIG_DPP_RESET = 0, @@ -23,6 +24,7 @@ enum SIG_DPP { SIG_DPP_RX_ACTION, SIG_DPP_LISTEN_NEXT_CHANNEL, SIG_DPP_DEL_TASK, + SIG_DPP_START_NET_INTRO, SIG_DPP_MAX, }; @@ -54,6 +56,7 @@ struct esp_dpp_context_t { }; int esp_supp_rx_action(uint8_t *hdr, uint8_t *payload, size_t len, uint8_t channel); +esp_err_t esp_dpp_post_evt(uint32_t evt_id, uint32_t data); #ifdef CONFIG_ESP_WIFI_DPP_SUPPORT bool is_dpp_enabled(void); diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.h b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.h index 27e53703f284..fc7bcb6c8b9e 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.h +++ b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.h @@ -18,6 +18,10 @@ bool hostap_deinit(void *data); u16 esp_send_assoc_resp(struct hostapd_data *data, struct sta_info *sta, const u8 *addr, u16 status_code, bool omit_rsnxe, int subtype); +int esp_send_sae_auth_reply(struct hostapd_data *hapd, + const u8 *dst, const u8 *bssid, + u16 auth_alg, u16 auth_transaction, u16 resp, + const u8 *ies, size_t ies_len); #endif #ifdef __cplusplus diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h b/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h index 0837ef1f0b5d..226fd7660e36 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h @@ -73,6 +73,7 @@ enum { WPA2_AUTH_FT_PSK = 0x0e, WPA3_AUTH_OWE = 0x0f, WPA3_AUTH_PSK_EXT_KEY = 0x10, + WPA3_AUTH_DPP = 0x11, WPA2_AUTH_INVALID }; @@ -296,6 +297,7 @@ bool esp_wifi_ap_notify_node_sae_auth_done(uint8_t *mac); bool esp_wifi_ap_is_sta_sae_reauth_node(uint8_t *mac); uint8_t* esp_wifi_sta_get_sae_identifier_internal(void); bool esp_wifi_eb_tx_status_success_internal(void *eb); -uint8_t* esp_wifi_sta_get_rsnxe(void); +uint8_t* esp_wifi_sta_get_rsnxe(u8 *bssid); +esp_err_t esp_wifi_sta_connect_internal(const uint8_t *bssid); #endif /* _ESP_WIFI_DRIVER_H_ */ diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c b/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c index ab926caad426..063ed705b6a2 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c @@ -43,7 +43,7 @@ static esp_err_t wpa3_build_sae_commit(u8 *bssid, size_t *sae_msg_len) use_pt = 1; } - rsnxe = esp_wifi_sta_get_rsnxe(); + rsnxe = esp_wifi_sta_get_rsnxe(bssid); if (rsnxe && rsnxe[1] >= 1) { rsnxe_capa = rsnxe[2]; } diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_wpa3_i.h b/components/wpa_supplicant/esp_supplicant/src/esp_wpa3_i.h index f00c769ddb50..198a52d8a49b 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wpa3_i.h +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wpa3_i.h @@ -57,10 +57,6 @@ int wpa3_hostap_post_evt(uint32_t evt_id, uint32_t data); void esp_wifi_register_wpa3_ap_cb(struct wpa_funcs *wpa_cb); int wpa3_hostap_auth_init(void *data); bool wpa3_hostap_auth_deinit(void); -int esp_send_sae_auth_reply(struct hostapd_data *hapd, - const u8 *dst, const u8 *bssid, - u16 auth_alg, u16 auth_transaction, u16 resp, - const u8 *ies, size_t ies_len); #else /* CONFIG_SAE */ diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c b/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c index 6f3c69110f2a..02f2805fc6c2 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c @@ -40,6 +40,11 @@ #include "wps/wps_defs.h" #include "wps/wps.h" +#ifdef CONFIG_DPP +#include "common/dpp.h" +#include "esp_dpp_i.h" +#endif + const wifi_osi_funcs_t *wifi_funcs; struct wpa_funcs *wpa_cb; @@ -198,6 +203,26 @@ bool wpa_deattach(void) return true; } +#ifdef CONFIG_DPP +int dpp_connect(uint8_t *bssid, bool pdr_done) +{ + int res = 0; + if (!pdr_done) { + if (esp_wifi_sta_get_prof_authmode_internal() == WPA3_AUTH_DPP) { + esp_dpp_post_evt(SIG_DPP_START_NET_INTRO, (u32)bssid); + } + } else { + res = wpa_config_bss(bssid); + if (res) { + wpa_printf(MSG_DEBUG, "Rejecting bss, validation failed"); + return res; + } + res = esp_wifi_sta_connect_internal(bssid); + } + return res; +} +#endif + int wpa_sta_connect(uint8_t *bssid) { /* use this API to set AP specific IEs during connection */ @@ -213,7 +238,16 @@ int wpa_sta_connect(uint8_t *bssid) esp_set_assoc_ie((uint8_t *)bssid, NULL, 0, false); } - return 0; +#ifdef CONFIG_DPP + struct wpa_sm *sm = &gWpaSm; + if (sm->key_mgmt == WPA_KEY_MGMT_DPP) { + ret = dpp_connect(bssid, false); + } else +#endif + { + ret = esp_wifi_sta_connect_internal(bssid); + } + return ret; } void wpa_config_done(void) diff --git a/components/wpa_supplicant/src/ap/ieee802_11.c b/components/wpa_supplicant/src/ap/ieee802_11.c index e8dbc7f06715..15a6b4a6030e 100644 --- a/components/wpa_supplicant/src/ap/ieee802_11.c +++ b/components/wpa_supplicant/src/ap/ieee802_11.c @@ -18,6 +18,7 @@ #include "ap/comeback_token.h" #include "crypto/random.h" #include "esp_wpa3_i.h" +#include "esp_hostap.h" #ifdef CONFIG_SAE diff --git a/components/wpa_supplicant/src/common/defs.h b/components/wpa_supplicant/src/common/defs.h index 36d37d6e6a95..99759b3c6f5d 100644 --- a/components/wpa_supplicant/src/common/defs.h +++ b/components/wpa_supplicant/src/common/defs.h @@ -49,6 +49,7 @@ typedef enum { FALSE = 0, TRUE = 1 } Boolean; #define WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 BIT(17) #define WPA_KEY_MGMT_OWE BIT(22) #define WPA_KEY_MGMT_SAE_EXT_KEY BIT(26) +#define WPA_KEY_MGMT_DPP BIT(23) static inline int wpa_key_mgmt_wpa_ieee8021x(int akm) { @@ -101,7 +102,8 @@ static inline int wpa_key_mgmt_sha256(int akm) WPA_KEY_MGMT_OSEN | WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_IEEE8021X_SUITE_B | - WPA_KEY_MGMT_OWE)); + WPA_KEY_MGMT_OWE | + WPA_KEY_MGMT_DPP)); } static inline int wpa_key_mgmt_sha384(int akm) @@ -120,6 +122,11 @@ static inline int wpa_key_mgmt_owe(int akm) return akm == WPA_KEY_MGMT_OWE; } +static inline int wpa_key_mgmt_dpp(int akm) +{ + return akm == WPA_KEY_MGMT_DPP; +} + static inline int wpa_key_mgmt_wpa(int akm) { return wpa_key_mgmt_wpa_ieee8021x(akm) || @@ -143,7 +150,8 @@ static inline int wpa_key_mgmt_supports_caching(int akm) { return wpa_key_mgmt_wpa_ieee8021x(akm) || wpa_key_mgmt_sae(akm) || - wpa_key_mgmt_owe(akm); + wpa_key_mgmt_owe(akm) || + wpa_key_mgmt_dpp(akm); } #endif diff --git a/components/wpa_supplicant/src/common/dpp.c b/components/wpa_supplicant/src/common/dpp.c index 9d3507ad3a72..b5d57d1e0182 100644 --- a/components/wpa_supplicant/src/common/dpp.c +++ b/components/wpa_supplicant/src/common/dpp.c @@ -52,6 +52,9 @@ static const struct dpp_curve_params dpp_curves[] = { { NULL, 0, 0, 0, 0, NULL, 0, NULL } }; +#define TRANSACTION_ID_ATTR_SET_LEN 5 +#define CONNECTOR_ATTR_SET_LEN 4 + static struct wpabuf * gas_build_req(u8 action, u8 dialog_token, size_t size) { @@ -1305,6 +1308,87 @@ static struct wpabuf * dpp_auth_build_resp(struct dpp_authentication *auth, return msg; } +struct wpabuf * dpp_build_peer_disc_req(struct dpp_authentication *auth, struct dpp_config_obj *conf) +{ + struct wpabuf *msg; + size_t len; + struct os_time now; + + if (!conf || !conf->connector || !auth || !auth->net_access_key || !conf->c_sign_key) { + wpa_printf(MSG_ERROR, "missing %s", !conf->connector ? "Connector" : !auth->net_access_key ? "netAccessKey" : "C-sign-key"); + return NULL; + } + + os_get_time(&now); + + if (auth->net_access_key_expiry && + (os_time_t) auth->net_access_key_expiry < now.sec) { + wpa_printf(MSG_ERROR, "netAccessKey expired"); + return NULL; + } + + wpa_printf(MSG_DEBUG, + "DPP: Starting network introduction protocol to derive PMKSA for " + MACSTR, MAC2STR(auth->peer_mac_addr)); + + len = TRANSACTION_ID_ATTR_SET_LEN + CONNECTOR_ATTR_SET_LEN + os_strlen(conf->connector); + msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_REQ, len); + if (!msg) { + return NULL; + } + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - no Transaction ID"); + goto skip_trans_id; + } + if (dpp_test == DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - invalid Transaction ID"); + wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID); + wpabuf_put_le16(msg, 0); + goto skip_trans_id; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* Transaction ID */ + wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID); + wpabuf_put_le16(msg, 1); + wpabuf_put_u8(msg, TRANSACTION_ID); + +#ifdef CONFIG_TESTING_OPTIONS +skip_trans_id: + if (dpp_test == DPP_TEST_NO_CONNECTOR_PEER_DISC_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - no Connector"); + goto skip_connector; + } + if (dpp_test == DPP_TEST_INVALID_CONNECTOR_PEER_DISC_REQ) { + char *connector; + + wpa_printf(MSG_INFO, "DPP: TESTING - invalid Connector"); + connector = dpp_corrupt_connector_signature( conf->connector); + if (!connector) { + wpabuf_free(msg); + return NULL; + } + wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR); + wpabuf_put_le16(msg, os_strlen(connector)); + wpabuf_put_str(msg, connector); + os_free(connector); + goto skip_connector; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* DPP Connector */ + wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR); + wpabuf_put_le16(msg, os_strlen(conf->connector)); + wpabuf_put_str(msg, conf->connector); + +#ifdef CONFIG_TESTING_OPTIONS +skip_connector: +#endif /* CONFIG_TESTING_OPTIONS */ + return msg; +} + static int dpp_channel_ok_init(struct hostapd_hw_modes *own_modes, u16 num_modes, unsigned int freq) @@ -4557,7 +4641,7 @@ dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start, static struct wpabuf * dpp_parse_jws_prot_hdr(const struct dpp_curve_params *curve, - const u8 *prot_hdr, u16 prot_hdr_len) + const u8 *prot_hdr, u16 prot_hdr_len, int *hash_func) { struct json_token *root, *token; struct wpabuf *kid = NULL; @@ -4603,6 +4687,14 @@ dpp_parse_jws_prot_hdr(const struct dpp_curve_params *curve, goto fail; } + if (os_strcmp(token->string, "ES256") == 0 || + os_strcmp(token->string, "BS256") == 0) { + *hash_func = CRYPTO_HASH_ALG_SHA256; + } else { + *hash_func = -1; + wpa_printf(MSG_ERROR, "Unsupported JWS Protected Header alg=%s", token->string); + } + kid = json_get_member_base64url(root, "kid"); if (!kid) { wpa_printf(MSG_DEBUG, "DPP: No kid string value found"); @@ -4980,6 +5072,7 @@ static void dpp_copy_netaccesskey(struct dpp_authentication *auth, return; wpabuf_free(auth->net_access_key); auth->net_access_key = wpabuf_alloc_copy(der, der_len); + crypto_free_buffer(der); } @@ -4996,11 +5089,12 @@ dpp_process_signed_connector(struct dpp_signed_connector_info *info, const char *pos, *end, *signed_start, *signed_end; struct wpabuf *kid = NULL; unsigned char *prot_hdr = NULL, *signature = NULL; - size_t prot_hdr_len = 0, signature_len = 0; + size_t prot_hdr_len = 0, signature_len = 0, signed_len; struct crypto_bignum *r = NULL, *s = NULL; const struct dpp_curve_params *curve; const struct crypto_ec_group *group; - int id; + int id, hash_func = -1; + u8 *hash = NULL; group = crypto_ec_get_group_from_key(csign_pub); if (!group) @@ -5029,7 +5123,7 @@ dpp_process_signed_connector(struct dpp_signed_connector_info *info, wpa_hexdump_ascii(MSG_DEBUG, "DPP: signedConnector - JWS Protected Header", (u8 *)prot_hdr, prot_hdr_len); - kid = dpp_parse_jws_prot_hdr(curve, prot_hdr, prot_hdr_len); + kid = dpp_parse_jws_prot_hdr(curve, prot_hdr, prot_hdr_len, &hash_func); if (!kid) { ret = DPP_STATUS_INVALID_CONNECTOR; goto fail; @@ -5090,13 +5184,31 @@ dpp_process_signed_connector(struct dpp_signed_connector_info *info, r = crypto_bignum_init_set(signature, signature_len / 2); s = crypto_bignum_init_set(signature + signature_len / 2, signature_len / 2); - if (!crypto_edcsa_sign_verify((unsigned char *)signed_start, r, s, - csign_pub, signed_end - signed_start + 1)) { + signed_len = signed_end - signed_start + 1; + hash = os_malloc(curve->hash_len); + if (!hash) { + wpa_printf(MSG_ERROR, "malloc failed"); + goto fail; + } + + if (hash_func == CRYPTO_HASH_ALG_SHA256) { + if ((sha256_vector(1, (const u8 **) &signed_start, &signed_len, hash)) != 0) { + goto fail; + } + } else { + goto fail; + } + + if ((crypto_edcsa_sign_verify((unsigned char *)hash, r, s, + csign_pub, curve->hash_len)) != 0) { goto fail; } ret = DPP_STATUS_OK; fail: + if (hash != NULL) { + os_free(hash); + } os_free(prot_hdr); wpabuf_free(kid); os_free(signature); diff --git a/components/wpa_supplicant/src/common/dpp.h b/components/wpa_supplicant/src/common/dpp.h index 6c588a5ffe16..61c056c380a6 100644 --- a/components/wpa_supplicant/src/common/dpp.h +++ b/components/wpa_supplicant/src/common/dpp.h @@ -30,6 +30,10 @@ struct dpp_global; #define PMK_LEN_SUITE_B_192 48 #define PMK_LEN_MAX 64 +/* Use a hardcoded Transaction ID 1 in Peer Discovery frames since there is only + * a single transaction in progress at any point in time. */ +static const u8 TRANSACTION_ID = 1; + /* DPP events */ #define DPP_EVENT_AUTH_SUCCESS "DPP-AUTH-SUCCESS " #define DPP_EVENT_AUTH_INIT_FAILED "DPP-AUTH-INIT-FAILED " @@ -502,6 +506,7 @@ struct wpabuf * dpp_build_conn_status_result(struct dpp_authentication *auth, enum dpp_status_error result, const u8 *ssid, size_t ssid_len, const char *channel_list); +struct wpabuf * dpp_build_peer_disc_req(struct dpp_authentication *auth, struct dpp_config_obj *conf); struct wpabuf * dpp_alloc_msg(enum dpp_public_action_frame_type type, size_t len); const u8 * dpp_get_attr(const u8 *buf, size_t len, u16 req_id, u16 *ret_len); @@ -586,6 +591,8 @@ struct dpp_global_config { struct dpp_global * dpp_global_init(struct dpp_global_config *config); void dpp_global_clear(struct dpp_global *dpp); void dpp_global_deinit(struct dpp_global *dpp); +int dpp_connect(uint8_t *bssid, bool pdr_done); +esp_err_t esp_dpp_start_net_intro_protocol(uint8_t *bssid); #endif /* CONFIG_DPP */ #endif /* DPP_H */ diff --git a/components/wpa_supplicant/src/common/wpa_common.c b/components/wpa_supplicant/src/common/wpa_common.c index d8f0e90c0e0b..d76e3a26ffe1 100644 --- a/components/wpa_supplicant/src/common/wpa_common.c +++ b/components/wpa_supplicant/src/common/wpa_common.c @@ -348,6 +348,11 @@ static int rsn_key_mgmt_to_bitfield(const u8 *s) if(RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_OWE) return WPA_KEY_MGMT_OWE; #endif /* CONFIG_OWE_STA */ +#ifdef CONFIG_DPP + if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_DPP) + return WPA_KEY_MGMT_DPP; +#endif /* CONFIG_DPP */ + return 0; } @@ -855,19 +860,31 @@ int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce, */ int wpa_use_akm_defined(int akmp){ - return akmp == WPA_KEY_MGMT_OSEN || - akmp == WPA_KEY_MGMT_OWE || - wpa_key_mgmt_sae(akmp) || - wpa_key_mgmt_suite_b(akmp); + return akmp == WPA_KEY_MGMT_OSEN || + akmp == WPA_KEY_MGMT_OWE || + akmp == WPA_KEY_MGMT_DPP || + wpa_key_mgmt_sae(akmp) || + wpa_key_mgmt_suite_b(akmp); } +/** + * wpa_use_aes_key_wrap - Is AES Keywrap algorithm used for EAPOL-Key Key Data + * @akmp: WPA_KEY_MGMT_* used in key derivation + * Returns: 1 if AES Keywrap is used; 0 otherwise + * + * Note: AKM 00-0F-AC:1 and 00-0F-AC:2 have special rules for selecting whether + * to use AES Keywrap based on the negotiated pairwise cipher. This function + * does not cover those special cases. + */ int wpa_use_aes_key_wrap(int akmp) { - return akmp == WPA_KEY_MGMT_OSEN || - wpa_key_mgmt_ft(akmp) || - wpa_key_mgmt_sha256(akmp) || - wpa_key_mgmt_sae(akmp) || - wpa_key_mgmt_suite_b(akmp); + return akmp == WPA_KEY_MGMT_OSEN || + akmp == WPA_KEY_MGMT_OWE || + akmp == WPA_KEY_MGMT_DPP || + wpa_key_mgmt_ft(akmp) || + wpa_key_mgmt_sha256(akmp) || + wpa_key_mgmt_sae(akmp) || + wpa_key_mgmt_suite_b(akmp); } /** @@ -958,6 +975,24 @@ int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver, break; #endif /* CONFIG_OWE_STA */ +#ifdef CONFIG_DPP + case WPA_KEY_MGMT_DPP: + wpa_printf(MSG_DEBUG, + "WPA: EAPOL-Key MIC using HMAC-SHA%u (AKM-defined - DPP)", + (unsigned int) key_len * 8 * 2); + if (key_len == 128 / 8) { + if (hmac_sha256(key, key_len, buf, len, hash)) + return -1; + } else { + wpa_printf(MSG_INFO, + "DPP: Unsupported KCK length: %u", + (unsigned int) key_len); + return -1; + } + os_memcpy(mic, hash, key_len); + break; +#endif /* CONFIG_DPP */ + #endif /* CONFIG_IEEE80211W */ default: return -1; diff --git a/components/wpa_supplicant/src/common/wpa_common.h b/components/wpa_supplicant/src/common/wpa_common.h index 78148c7eb104..8f8071962e0b 100644 --- a/components/wpa_supplicant/src/common/wpa_common.h +++ b/components/wpa_supplicant/src/common/wpa_common.h @@ -70,6 +70,7 @@ RSN_SELECTOR(0x00, 0x0f, 0xac, 13) #define RSN_AUTH_KEY_MGMT_FT_SAE RSN_SELECTOR(0x00, 0x0f, 0xac, 9) #define RSN_AUTH_KEY_MGMT_OWE RSN_SELECTOR(0x00, 0x0f, 0xac, 18) #define RSN_AUTH_KEY_MGMT_SAE_EXT_KEY RSN_SELECTOR(0x00, 0x0f, 0xac, 24) +#define RSN_AUTH_KEY_MGMT_DPP RSN_SELECTOR(0x50, 0x6f, 0x9a, 0x02) #define RSN_CIPHER_SUITE_NONE RSN_SELECTOR(0x00, 0x0f, 0xac, 0) #define RSN_CIPHER_SUITE_WEP40 RSN_SELECTOR(0x00, 0x0f, 0xac, 1) diff --git a/components/wpa_supplicant/src/rsn_supp/pmksa_cache.c b/components/wpa_supplicant/src/rsn_supp/pmksa_cache.c index eedb29fac6c9..8ed1bdc2e773 100644 --- a/components/wpa_supplicant/src/rsn_supp/pmksa_cache.c +++ b/components/wpa_supplicant/src/rsn_supp/pmksa_cache.c @@ -108,7 +108,7 @@ pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, const u8 *pmkid, const u8 *kck, size_t kck_len, const u8 *aa, const u8 *spa, void *network_ctx, int akmp) { - struct rsn_pmksa_cache_entry *entry, *pos, *prev; + struct rsn_pmksa_cache_entry *entry; struct os_reltime now; if (pmk_len > PMK_LEN_MAX) @@ -139,14 +139,23 @@ pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, os_memcpy(entry->aa, aa, ETH_ALEN); entry->network_ctx = network_ctx; + return pmksa_cache_add_entry(pmksa, entry); +} + +struct rsn_pmksa_cache_entry * +pmksa_cache_add_entry(struct rsn_pmksa_cache *pmksa, + struct rsn_pmksa_cache_entry *entry) +{ + struct rsn_pmksa_cache_entry *pos, *prev; + /* Replace an old entry for the same Authenticator (if found) with the * new entry */ pos = pmksa->pmksa; prev = NULL; while (pos) { - if (os_memcmp(aa, pos->aa, ETH_ALEN) == 0) { - if (pos->pmk_len == pmk_len && - os_memcmp_const(pos->pmk, pmk, pmk_len) == 0 && + if (os_memcmp(entry->aa, pos->aa, ETH_ALEN) == 0) { + if (pos->pmk_len == entry->pmk_len && + os_memcmp_const(pos->pmk, entry->pmk, entry->pmk_len) == 0 && os_memcmp_const(pos->pmkid, entry->pmkid, PMKID_LEN) == 0) { wpa_printf(MSG_DEBUG, "WPA: reusing previous " @@ -172,7 +181,7 @@ pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, "the current AP and any PMKSA cache entry " "that was based on the old PMK"); if (!pos->opportunistic) - pmksa_cache_flush(pmksa, network_ctx, pos->pmk, + pmksa_cache_flush(pmksa, entry->network_ctx, pos->pmk, pos->pmk_len); pmksa_cache_free_entry(pmksa, pos, PMKSA_REPLACE); break; @@ -224,7 +233,7 @@ pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, } pmksa->pmksa_count++; wpa_printf(MSG_DEBUG, "RSN: Added PMKSA cache entry for " MACSTR - " network_ctx=%p", MAC2STR(entry->aa), network_ctx); + " network_ctx=%p", MAC2STR(entry->aa), entry->network_ctx); return entry; } diff --git a/components/wpa_supplicant/src/rsn_supp/pmksa_cache.h b/components/wpa_supplicant/src/rsn_supp/pmksa_cache.h index 040abc064331..2bdf3d4d1564 100644 --- a/components/wpa_supplicant/src/rsn_supp/pmksa_cache.h +++ b/components/wpa_supplicant/src/rsn_supp/pmksa_cache.h @@ -59,6 +59,9 @@ struct rsn_pmksa_cache_entry * pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, const u8 *pmkid, const u8 *kck, size_t kck_len, const u8 *aa, const u8 *spa, void *network_ctx, int akmp); +struct rsn_pmksa_cache_entry * +pmksa_cache_add_entry(struct rsn_pmksa_cache *pmksa, + struct rsn_pmksa_cache_entry *entry); struct rsn_pmksa_cache_entry * pmksa_cache_get_current(struct wpa_sm *sm); void pmksa_cache_clear_current(struct wpa_sm *sm); int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid, diff --git a/components/wpa_supplicant/src/rsn_supp/wpa.c b/components/wpa_supplicant/src/rsn_supp/wpa.c index a3c380ca815d..298d414c9fc0 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa.c +++ b/components/wpa_supplicant/src/rsn_supp/wpa.c @@ -36,6 +36,7 @@ #include "esp_owe_i.h" #include "common/sae.h" #include "esp_eap_client_i.h" +#include "esp_wpa3_i.h" /** * eapol_sm_notify_eap_success - Notification of external EAP success trigger @@ -285,14 +286,12 @@ static void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise) int key_info, ver; u8 bssid[ETH_ALEN], *rbuf, *key_mic; - if (sm->key_mgmt == WPA_KEY_MGMT_OSEN || wpa_key_mgmt_suite_b(sm->key_mgmt)) + if (wpa_use_akm_defined(sm->key_mgmt)) ver = WPA_KEY_INFO_TYPE_AKM_DEFINED; else if (wpa_key_mgmt_ft(sm->key_mgmt) || wpa_key_mgmt_sha256(sm->key_mgmt)) ver = WPA_KEY_INFO_TYPE_AES_128_CMAC; else if (sm->pairwise_cipher != WPA_CIPHER_TKIP) ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; - else if (sm->key_mgmt == WPA_KEY_MGMT_SAE || sm->key_mgmt == WPA_KEY_MGMT_OWE) - ver = 0; else ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; @@ -848,7 +847,7 @@ void wpa_supplicant_key_neg_complete(struct wpa_sm *sm, sm, addr, MLME_SETPROTECTION_PROTECT_TYPE_RX_TX, MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); - if (wpa_key_mgmt_wpa_psk(sm->key_mgmt) || sm->key_mgmt == WPA_KEY_MGMT_OWE) + if (wpa_key_mgmt_wpa_psk(sm->key_mgmt) || sm->key_mgmt == WPA_KEY_MGMT_OWE || sm->key_mgmt == WPA_KEY_MGMT_DPP) eapol_sm_notify_eap_success(TRUE); /* * Start preauthentication after a short wait to avoid a @@ -2280,17 +2279,19 @@ void wpa_set_profile(u32 wpa_proto, u8 auth_mode) } else if (auth_mode == WPA2_AUTH_PSK_SHA256) { sm->key_mgmt = WPA_KEY_MGMT_PSK_SHA256; } else if (auth_mode == WPA3_AUTH_PSK) { - sm->key_mgmt = WPA_KEY_MGMT_SAE; /* for WPA3 PSK */ + sm->key_mgmt = WPA_KEY_MGMT_SAE; /* for WPA3 PSK */ } else if (auth_mode == WAPI_AUTH_PSK) { - sm->key_mgmt = WPA_KEY_MGMT_WAPI_PSK; /* for WAPI PSK */ + sm->key_mgmt = WPA_KEY_MGMT_WAPI_PSK; /* for WAPI PSK */ } else if (auth_mode == WPA2_AUTH_ENT_SHA384_SUITE_B) { - sm->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192; + sm->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192; } else if (auth_mode == WPA2_AUTH_FT_PSK) { - sm->key_mgmt = WPA_KEY_MGMT_FT_PSK; + sm->key_mgmt = WPA_KEY_MGMT_FT_PSK; } else if (auth_mode == WPA3_AUTH_OWE) { - sm->key_mgmt = WPA_KEY_MGMT_OWE; + sm->key_mgmt = WPA_KEY_MGMT_OWE; } else if (auth_mode == WPA3_AUTH_PSK_EXT_KEY) { - sm->key_mgmt = WPA_KEY_MGMT_SAE_EXT_KEY; /* for WPA3 PSK */ + sm->key_mgmt = WPA_KEY_MGMT_SAE_EXT_KEY; /* for WPA3 PSK */ + } else if (auth_mode == WPA3_AUTH_DPP) { + sm->key_mgmt = WPA_KEY_MGMT_DPP; } else { sm->key_mgmt = WPA_KEY_MGMT_PSK; /* fixed to PSK for now */ } @@ -2472,7 +2473,8 @@ wpa_set_passphrase(char * passphrase, u8 *ssid, size_t ssid_len) */ if (sm->key_mgmt == WPA_KEY_MGMT_SAE || sm->key_mgmt == WPA_KEY_MGMT_OWE || - sm->key_mgmt == WPA_KEY_MGMT_SAE_EXT_KEY) + sm->key_mgmt == WPA_KEY_MGMT_SAE_EXT_KEY || + sm->key_mgmt == WPA_KEY_MGMT_DPP) return; /* This is really SLOW, so just re cacl while reset param */ diff --git a/components/wpa_supplicant/src/rsn_supp/wpa_ie.c b/components/wpa_supplicant/src/rsn_supp/wpa_ie.c index 34969aee6c91..789c0958c650 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa_ie.c +++ b/components/wpa_supplicant/src/rsn_supp/wpa_ie.c @@ -198,6 +198,10 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, } else if (key_mgmt == WPA_KEY_MGMT_OWE) { RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_OWE); #endif /* CONFIG_OWE_STA */ +#ifdef CONFIG_DPP + } else if (key_mgmt & WPA_KEY_MGMT_DPP) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_DPP); +#endif /* CONFIG_DPP */ #endif /* CONFIG_IEEE80211W */ } else if (key_mgmt == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) { RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192); diff --git a/examples/wifi/wifi_easy_connect/dpp-enrollee/README.md b/examples/wifi/wifi_easy_connect/dpp-enrollee/README.md index 0415b814d3e2..c3ff6a0b4b6c 100644 --- a/examples/wifi/wifi_easy_connect/dpp-enrollee/README.md +++ b/examples/wifi/wifi_easy_connect/dpp-enrollee/README.md @@ -3,24 +3,24 @@ # Device Provisioning Protocol (Enrollee) Example -This example shows how to configure ESP32 as an enrollee using Device Provisioning Protocol(DPP) also known as Wi-Fi Easy Connect. +This example shows how to configure ESP devices as an enrollee using Device Provisioning Protocol(DPP) also known as Wi-Fi Easy Connect. -DPP provides a simple and secure way to onboard ESP32 to a network. -We now support Responder-Enrollee mode of DPP with PSK mode of authentication. +DPP provides a simple and secure way to onboard ESP devices to a network. +We now support DPP in Responder-Enrollee mode with AKM types PSK and DPP. You need a Wi-Fi Easy Connect with Initiator mode capable device to make use of this example. Some Android 10+ devices have this capability. (Vendor specific) To run the example with an Android 10+ device follow below steps - -1. Compile and flash the example on ESP32, a QR code will appear on your console. +1. Compile and flash the example on ESP device, a QR code will appear on your console. 2. Connect your phone to the network, say named "Example-AP". 3. Now go to Settings->WiFi & Internet->Wi-Fi->Example-AP->Advanced->Add Device. -4. Scan QR Code using the scanner, which will make ESP32 connect to Example-AP. +4. Scan QR Code using the scanner, which will make ESP device connect to Example-AP. Optional configuration available *Note:* - QR Code should be displayed as dark on a white/light background to work properly. -- If displayed QR Code had line gaps, try switching to a new font or a diiferent Terminal program. See below QR Code for for checking beforehand. +- If displayed QR Code had line gaps, try switching to a new font or a different Terminal program. See below QR Code for checking beforehand. ### Example output diff --git a/examples/wifi/wifi_easy_connect/dpp-enrollee/main/dpp_enrollee_main.c b/examples/wifi/wifi_easy_connect/dpp-enrollee/main/dpp_enrollee_main.c index 76a8fee4079c..a5af57587a2d 100644 --- a/examples/wifi/wifi_easy_connect/dpp-enrollee/main/dpp_enrollee_main.c +++ b/examples/wifi/wifi_easy_connect/dpp-enrollee/main/dpp_enrollee_main.c @@ -18,7 +18,7 @@ #include "nvs_flash.h" #include "qrcode.h" -#ifdef CONFIG_ESP_DPP_LISTEN_CHANNEL +#ifdef CONFIG_ESP_DPP_LISTEN_CHANNEL_LIST #define EXAMPLE_DPP_LISTEN_CHANNEL_LIST CONFIG_ESP_DPP_LISTEN_CHANNEL_LIST #else #define EXAMPLE_DPP_LISTEN_CHANNEL_LIST "6" @@ -49,6 +49,7 @@ static EventGroupHandle_t s_dpp_event_group; #define DPP_CONNECTED_BIT BIT0 #define DPP_CONNECT_FAIL_BIT BIT1 #define DPP_AUTH_FAIL_BIT BIT2 +#define WIFI_MAX_RETRY_NUM 3 static void event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) @@ -57,7 +58,7 @@ static void event_handler(void *arg, esp_event_base_t event_base, ESP_ERROR_CHECK(esp_supp_dpp_start_listen()); ESP_LOGI(TAG, "Started listening for DPP Authentication"); } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { - if (s_retry_num < 5) { + if (s_retry_num < WIFI_MAX_RETRY_NUM) { esp_wifi_connect(); s_retry_num++; ESP_LOGI(TAG, "retry to connect to the AP"); @@ -65,6 +66,8 @@ static void event_handler(void *arg, esp_event_base_t event_base, xEventGroupSetBits(s_dpp_event_group, DPP_CONNECT_FAIL_BIT); } ESP_LOGI(TAG, "connect to the AP fail"); + } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_CONNECTED) { + ESP_LOGI(TAG, "Successfully connected to the AP ssid : %s ", s_dpp_wifi_config.sta.ssid); } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { ip_event_got_ip_t *event = (ip_event_got_ip_t *) event_data; ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip)); @@ -86,10 +89,8 @@ void dpp_enrollee_event_cb(esp_supp_dpp_event_t event, void *data) break; case ESP_SUPP_DPP_CFG_RECVD: memcpy(&s_dpp_wifi_config, data, sizeof(s_dpp_wifi_config)); - esp_wifi_set_config(ESP_IF_WIFI_STA, &s_dpp_wifi_config); - ESP_LOGI(TAG, "DPP Authentication successful, connecting to AP : %s", - s_dpp_wifi_config.sta.ssid); s_retry_num = 0; + esp_wifi_set_config(ESP_IF_WIFI_STA, &s_dpp_wifi_config); esp_wifi_connect(); break; case ESP_SUPP_DPP_FAIL: @@ -155,9 +156,9 @@ void dpp_enrollee_init(void) wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); ESP_ERROR_CHECK(esp_supp_dpp_init(dpp_enrollee_event_cb)); ESP_ERROR_CHECK(dpp_enrollee_bootstrap()); - ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); ESP_ERROR_CHECK(esp_wifi_start()); /* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum