mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
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:
commit
2a6b3df49f
@ -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
|
@ -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
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
mbedtls_pk_free(pkey);
|
||||
os_free(pkey);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int crypto_is_ec_key(struct crypto_key *key)
|
||||
|
@ -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,9 +411,8 @@ 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]);
|
||||
@ -298,7 +420,13 @@ static void esp_dpp_rx_auth(struct action_rx_param *rx_param)
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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_ */
|
||||
|
@ -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];
|
||||
}
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
@ -857,13 +862,25 @@ 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 ||
|
||||
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 ||
|
||||
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) ||
|
||||
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
@ -2291,6 +2290,8 @@ void wpa_set_profile(u32 wpa_proto, u8 auth_mode)
|
||||
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 */
|
||||
} 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 */
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user