Merge branch 'feature/support_DPP_AKM_v1' into 'master'

Add support of Network Introduction Protocol in DPP.

Closes WIFI-6171 and WIFIBUG-156

See merge request espressif/esp-idf!20856
This commit is contained in:
Jiang Jiang Jian 2024-02-22 10:35:07 +08:00
commit 2a6b3df49f
23 changed files with 527 additions and 116 deletions

View File

@ -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;

@ -1 +1 @@
Subproject commit 62ed01cb7946633ca315757edbd0e333ecf7be72
Subproject commit 952cacbb3511df026d0753ffb141e289ffd12493

View File

@ -10,6 +10,7 @@
#include <stdbool.h>
#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
}

View File

@ -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);
*key_len = mbedtls_pk_write_key_der(pkey, (unsigned char *)der_data, ECP_PRV_DER_MAX_BYTES);
if (*key_len <= 0)
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) {
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 @@ fail:
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)

View File

@ -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 @@ fail:
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 @@ fail:
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 @@ init_fail:
}
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

View File

@ -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);

View File

@ -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

View File

@ -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_ */

View File

@ -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];
}

View File

@ -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 */

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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 @@ skip_wrapped_data:
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 @@ fail:
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);

View File

@ -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 */

View File

@ -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;

View File

@ -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)

View File

@ -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;
}

View File

@ -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,

View File

@ -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 */

View File

@ -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);

View File

@ -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

View File

@ -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