Add DPP Enrollee Support

1. Modify DPP Protocol modules for our purpose
2. Add DPP supplicant task and modules to handle DPP frames
3. Add DPP Public API's and definitions for DPP
This commit is contained in:
Nachiket Kukade 2020-10-27 18:17:38 +05:30
parent 1ca80b4221
commit 87205dc2f4
10 changed files with 784 additions and 133 deletions

View File

@ -62,6 +62,9 @@
#if __has_include("ulp_common.h") #if __has_include("ulp_common.h")
#include "ulp_common.h" #include "ulp_common.h"
#endif #endif
#if __has_include("esp_supplicant/esp_dpp.h")
#include "esp_supplicant/esp_dpp.h"
#endif
#ifdef CONFIG_ESP_ERR_TO_NAME_LOOKUP #ifdef CONFIG_ESP_ERR_TO_NAME_LOOKUP
#define ERR_TBL_IT(err) {err, #err} #define ERR_TBL_IT(err) {err, #err}
@ -407,6 +410,25 @@ static const esp_err_msg_t esp_err_msg_table[] = {
# endif # endif
# ifdef ESP_ERR_ESPNOW_IF # ifdef ESP_ERR_ESPNOW_IF
ERR_TBL_IT(ESP_ERR_ESPNOW_IF), /* 12396 0x306c Interface error */ ERR_TBL_IT(ESP_ERR_ESPNOW_IF), /* 12396 0x306c Interface error */
# endif
// components/wpa_supplicant/include/esp_supplicant/esp_dpp.h
# ifdef ESP_ERR_DPP_FAILURE
ERR_TBL_IT(ESP_ERR_DPP_FAILURE), /* 12439 0x3097 Generic failure during DPP Operation */
# endif
# ifdef ESP_ERR_DPP_NO_MEM
ERR_TBL_IT(ESP_ERR_DPP_NO_MEM), /* 12440 0x3098 Failure to allocate memory in DPP Operation */
# endif
# ifdef ESP_ERR_DPP_TIMEOUT
ERR_TBL_IT(ESP_ERR_DPP_TIMEOUT), /* 12441 0x3099 DPP Operation timed out */
# endif
# ifdef ESP_ERR_DPP_TX_FAILURE
ERR_TBL_IT(ESP_ERR_DPP_TX_FAILURE), /* 12442 0x309a DPP Frame Tx failed OR not Acked */
# endif
# ifdef ESP_ERR_DPP_INVALID_ATTR
ERR_TBL_IT(ESP_ERR_DPP_INVALID_ATTR), /* 12443 0x309b Encountered invalid DPP Attribute */
# endif
# ifdef ESP_ERR_DPP_NOT_SUPPORTED
ERR_TBL_IT(ESP_ERR_DPP_NOT_SUPPORTED), /* 12444 0x309c DPP Configuration not supported */
# endif # endif
// components/esp_common/include/esp_err.h // components/esp_common/include/esp_err.h
# ifdef ESP_ERR_MESH_BASE # ifdef ESP_ERR_MESH_BASE

View File

@ -331,6 +331,12 @@ menu "Wi-Fi"
If neither of them are enabled, the other 7.4KB IRAM memory would be taken by this option. If neither of them are enabled, the other 7.4KB IRAM memory would be taken by this option.
Wi-Fi power-save mode average current would be reduced if this option is enabled. Wi-Fi power-save mode average current would be reduced if this option is enabled.
config ESP32_WIFI_OFFCHANNEL_OPS
bool "Enable Offchannel operations"
default n
help
Select this option to enable Offchannel Tx and Remain on Channel features.
endmenu # Wi-Fi endmenu # Wi-Fi
menu "PHY" menu "PHY"

View File

@ -18,7 +18,7 @@ set(srcs "port/os_xtensa.c"
"src/crypto/aes-omac1.c" "src/crypto/aes-omac1.c"
"src/crypto/aes-unwrap.c" "src/crypto/aes-unwrap.c"
"src/crypto/aes-wrap.c" "src/crypto/aes-wrap.c"
"src/crypto/aes-omac1.c" "src/crypto/sha256-tlsprf.c"
"src/crypto/bignum.c" "src/crypto/bignum.c"
"src/crypto/ccmp.c" "src/crypto/ccmp.c"
"src/crypto/crypto_mbedtls.c" "src/crypto/crypto_mbedtls.c"
@ -63,6 +63,7 @@ set(srcs "port/os_xtensa.c"
"src/esp_supplicant/esp_wpas_glue.c" "src/esp_supplicant/esp_wpas_glue.c"
"src/esp_supplicant/esp_wps.c" "src/esp_supplicant/esp_wps.c"
"src/esp_supplicant/esp_wpa3.c" "src/esp_supplicant/esp_wpa3.c"
"src/esp_supplicant/esp_dpp.c"
"src/rsn_supp/pmksa_cache.c" "src/rsn_supp/pmksa_cache.c"
"src/rsn_supp/wpa.c" "src/rsn_supp/wpa.c"
"src/rsn_supp/wpa_ie.c" "src/rsn_supp/wpa_ie.c"

View File

@ -0,0 +1,59 @@
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ESP_DPP_H
#define ESP_DPP_H
#include <stdbool.h>
#include "esp_err.h"
#ifdef __cplusplus
extern "C" {
#endif
#define ESP_ERR_DPP_FAILURE (ESP_ERR_WIFI_BASE + 151) /*!< Generic failure during DPP Operation */
#define ESP_ERR_DPP_NO_MEM (ESP_ERR_WIFI_BASE + 152) /*!< Failure to allocate memory in DPP Operation */
#define ESP_ERR_DPP_TIMEOUT (ESP_ERR_WIFI_BASE + 153) /*!< DPP Operation timed out */
#define ESP_ERR_DPP_TX_FAILURE (ESP_ERR_WIFI_BASE + 154) /*!< DPP Frame Tx failed OR not Acked */
#define ESP_ERR_DPP_INVALID_ATTR (ESP_ERR_WIFI_BASE + 155) /*!< Encountered invalid DPP Attribute */
#define ESP_ERR_DPP_NOT_SUPPORTED (ESP_ERR_WIFI_BASE + 156) /*!< Encountered invalid DPP Attribute */
enum dpp_bootstrap_type {
DPP_BOOTSTRAP_QR_CODE,
DPP_BOOTSTRAP_PKEX,
DPP_BOOTSTRAP_NFC_URI,
};
typedef enum {
WIFI_DPP_URI_READY,
WIFI_DPP_CFG_RECVD,
WIFI_DPP_FAIL,
} wifi_dpp_event_t;
typedef void (*wifi_dpp_event_cb_t)(wifi_dpp_event_t evt, void *data);
esp_err_t esp_supp_dpp_init(wifi_dpp_event_cb_t evt_cb);
void esp_supp_dpp_deinit(void);
esp_err_t esp_dpp_bootstrap_gen(uint8_t channel, enum dpp_bootstrap_type type,
const char *key, const char *info);
void esp_dpp_start_listen(uint8_t channel);
void esp_dpp_stop_listen(void);
#ifdef __cplusplus
}
#endif
#endif /* ESP_DPP_H */

View File

@ -2397,7 +2397,7 @@ struct dpp_authentication *
dpp_auth_req_rx(void *msg_ctx, u8 dpp_allowed_roles, int qr_mutual, dpp_auth_req_rx(void *msg_ctx, u8 dpp_allowed_roles, int qr_mutual,
struct dpp_bootstrap_info *peer_bi, struct dpp_bootstrap_info *peer_bi,
struct dpp_bootstrap_info *own_bi, struct dpp_bootstrap_info *own_bi,
unsigned int freq, const u8 *hdr, const u8 *attr_start, unsigned int curr_chan, const u8 *hdr, const u8 *attr_start,
size_t attr_len) size_t attr_len)
{ {
struct crypto_key *pi = NULL; struct crypto_key *pi = NULL;
@ -2406,10 +2406,8 @@ dpp_auth_req_rx(void *msg_ctx, u8 dpp_allowed_roles, int qr_mutual,
size_t len[2]; size_t len[2];
u8 *unwrapped = NULL; u8 *unwrapped = NULL;
size_t unwrapped_len = 0; size_t unwrapped_len = 0;
const u8 *wrapped_data, *i_proto, *i_nonce, *i_capab, *i_bootstrap, const u8 *wrapped_data, *i_proto, *i_nonce, *i_capab, *i_bootstrap;
*channel; u16 wrapped_data_len, i_proto_len, i_nonce_len, i_capab_len, i_bootstrap_len;
u16 wrapped_data_len, i_proto_len, i_nonce_len, i_capab_len,
i_bootstrap_len, channel_len;
struct dpp_authentication *auth = NULL; struct dpp_authentication *auth = NULL;
#ifdef CONFIG_WPA_TESTING_OPTIONS #ifdef CONFIG_WPA_TESTING_OPTIONS
@ -2438,10 +2436,11 @@ dpp_auth_req_rx(void *msg_ctx, u8 dpp_allowed_roles, int qr_mutual,
auth->peer_bi = peer_bi; auth->peer_bi = peer_bi;
auth->own_bi = own_bi; auth->own_bi = own_bi;
auth->curve = own_bi->curve; auth->curve = own_bi->curve;
auth->curr_freq = freq; auth->curr_chan = curr_chan;
auth->peer_version = 1; /* default to the first version */ auth->peer_version = 1; /* default to the first version */
#if 0
channel = dpp_get_attr(attr_start, attr_len, DPP_ATTR_CHANNEL, channel = dpp_get_attr(attr_start, attr_len, DPP_ATTR_CHANNEL,
&channel_len); &channel_len);
if (channel) { if (channel) {
@ -2452,7 +2451,6 @@ dpp_auth_req_rx(void *msg_ctx, u8 dpp_allowed_roles, int qr_mutual,
goto fail; goto fail;
} }
#ifndef ESP_SUPPLICANT
neg_freq = ieee80211_chan_to_freq(NULL, channel[0], channel[1]); neg_freq = ieee80211_chan_to_freq(NULL, channel[0], channel[1]);
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
"DPP: Initiator requested different channel for negotiation: op_class=%u channel=%u --> freq=%d", "DPP: Initiator requested different channel for negotiation: op_class=%u channel=%u --> freq=%d",
@ -2469,10 +2467,10 @@ dpp_auth_req_rx(void *msg_ctx, u8 dpp_allowed_roles, int qr_mutual,
freq, neg_freq); freq, neg_freq);
auth->curr_freq = neg_freq; auth->curr_freq = neg_freq;
} }
#endif
/* rename it to chan */ /* rename it to chan */
auth->curr_freq = *channel; auth->curr_chan = *channel;
} }
#endif
i_proto = dpp_get_attr(attr_start, attr_len, DPP_ATTR_I_PROTOCOL_KEY, i_proto = dpp_get_attr(attr_start, attr_len, DPP_ATTR_I_PROTOCOL_KEY,
&i_proto_len); &i_proto_len);
@ -4630,7 +4628,7 @@ static int dpp_parse_cred_legacy(struct dpp_config_obj *conf,
(u8 *)pass->string, len); (u8 *)pass->string, len);
if (len < 8 || len > 63) if (len < 8 || len > 63)
return -1; return -1;
os_strlcpy(conf->passphrase, pass->string, os_strncpy(conf->passphrase, pass->string,
sizeof(conf->passphrase)); sizeof(conf->passphrase));
} else if (psk_hex && psk_hex->type == JSON_STRING) { } else if (psk_hex && psk_hex->type == JSON_STRING) {
if (dpp_akm_sae(conf->akm) && !dpp_akm_psk(conf->akm)) { if (dpp_akm_sae(conf->akm) && !dpp_akm_psk(conf->akm)) {
@ -5386,7 +5384,7 @@ fail:
int dpp_conf_resp_rx(struct dpp_authentication *auth, int dpp_conf_resp_rx(struct dpp_authentication *auth,
const struct wpabuf *resp) const uint8_t *resp, uint32_t resp_len)
{ {
const u8 *wrapped_data, *e_nonce, *status, *conf_obj; const u8 *wrapped_data, *e_nonce, *status, *conf_obj;
u16 wrapped_data_len, e_nonce_len, status_len, conf_obj_len; u16 wrapped_data_len, e_nonce_len, status_len, conf_obj_len;
@ -5398,12 +5396,12 @@ int dpp_conf_resp_rx(struct dpp_authentication *auth,
auth->conf_resp_status = 255; auth->conf_resp_status = 255;
if (dpp_check_attrs(wpabuf_head(resp), wpabuf_len(resp)) < 0) { if (dpp_check_attrs(resp, resp_len) < 0) {
dpp_auth_fail(auth, "Invalid attribute in config response"); dpp_auth_fail(auth, "Invalid attribute in config response");
return -1; return -1;
} }
wrapped_data = dpp_get_attr(wpabuf_head(resp), wpabuf_len(resp), wrapped_data = dpp_get_attr(resp, resp_len,
DPP_ATTR_WRAPPED_DATA, DPP_ATTR_WRAPPED_DATA,
&wrapped_data_len); &wrapped_data_len);
if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) { if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
@ -5419,8 +5417,8 @@ int dpp_conf_resp_rx(struct dpp_authentication *auth,
if (!unwrapped) if (!unwrapped)
return -1; return -1;
addr[0] = wpabuf_head(resp); addr[0] = resp;
len[0] = wrapped_data - 4 - (const u8 *) wpabuf_head(resp); len[0] = wrapped_data - 4 - resp;
wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD", addr[0], len[0]); wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD", addr[0], len[0]);
if (aes_siv_decrypt(auth->ke, auth->curve->hash_len, if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
@ -5451,7 +5449,7 @@ int dpp_conf_resp_rx(struct dpp_authentication *auth,
goto fail; goto fail;
} }
status = dpp_get_attr(wpabuf_head(resp), wpabuf_len(resp), status = dpp_get_attr(resp, resp_len,
DPP_ATTR_STATUS, &status_len); DPP_ATTR_STATUS, &status_len);
if (!status || status_len < 1) { if (!status || status_len < 1) {
dpp_auth_fail(auth, dpp_auth_fail(auth,
@ -6083,9 +6081,6 @@ int dpp_bootstrap_gen(struct dpp_global *dpp, const char *cmd)
int ret = -1; int ret = -1;
struct dpp_bootstrap_info *bi; struct dpp_bootstrap_info *bi;
if (!dpp)
return -1;
bi = os_zalloc(sizeof(*bi)); bi = os_zalloc(sizeof(*bi));
if (!bi) if (!bi)
goto fail; goto fail;
@ -6143,6 +6138,7 @@ int dpp_bootstrap_gen(struct dpp_global *dpp, const char *cmd)
mac ? "M:" : "", mac ? mac : "", mac ? ";" : "", mac ? "M:" : "", mac ? mac : "", mac ? ";" : "",
info ? "I:" : "", info ? info : "", info ? ";" : "", info ? "I:" : "", info ? info : "", info ? ";" : "",
pk); pk);
bi->id = dpp_next_id(dpp); bi->id = dpp_next_id(dpp);
dl_list_add(&dpp->bootstrap, &bi->list); dl_list_add(&dpp->bootstrap, &bi->list);
ret = bi->id; ret = bi->id;

View File

@ -13,8 +13,11 @@
#ifdef CONFIG_DPP #ifdef CONFIG_DPP
#include "utils/list.h" #include "utils/list.h"
#include "common/wpa_common.h"
#include "crypto/sha256.h" #include "crypto/sha256.h"
#include "utils/includes.h"
#include "utils/common.h"
#include "esp_err.h"
#include "esp_dpp.h"
struct crypto_ecdh; struct crypto_ecdh;
struct hostapd_ip_addr; struct hostapd_ip_addr;
@ -147,12 +150,6 @@ struct dpp_curve_params {
const char *jws_alg; const char *jws_alg;
}; };
enum dpp_bootstrap_type {
DPP_BOOTSTRAP_QR_CODE,
DPP_BOOTSTRAP_PKEX,
DPP_BOOTSTRAP_NFC_URI,
};
struct dpp_bootstrap_info { struct dpp_bootstrap_info {
struct dl_list list; struct dl_list list;
unsigned int id; unsigned int id;
@ -258,6 +255,7 @@ struct dpp_authentication {
* Authentication exchange */ * Authentication exchange */
unsigned int freq[DPP_BOOTSTRAP_MAX_FREQ]; unsigned int freq[DPP_BOOTSTRAP_MAX_FREQ];
unsigned int num_freq, freq_idx; unsigned int num_freq, freq_idx;
unsigned int curr_chan;
unsigned int curr_freq; unsigned int curr_freq;
unsigned int neg_freq; unsigned int neg_freq;
unsigned int num_freq_iters; unsigned int num_freq_iters;
@ -488,8 +486,8 @@ void dpp_auth_deinit(struct dpp_authentication *auth);
struct wpabuf * struct wpabuf *
dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start, dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start,
size_t attr_len); size_t attr_len);
int dpp_conf_resp_rx(struct dpp_authentication *auth, int dpp_conf_resp_rx(struct dpp_authentication *auth, const u8 *resp,
const struct wpabuf *resp); u32 resp_len);
enum dpp_status_error dpp_conf_result_rx(struct dpp_authentication *auth, enum dpp_status_error dpp_conf_result_rx(struct dpp_authentication *auth,
const u8 *hdr, const u8 *hdr,
const u8 *attr_start, size_t attr_len); const u8 *attr_start, size_t attr_len);

View File

@ -263,6 +263,13 @@
#define WLAN_ACTION_UNPROTECTED_WNM 11 #define WLAN_ACTION_UNPROTECTED_WNM 11
#define WLAN_ACTION_WMM 17 /* WMM Specification 1.1 */ #define WLAN_ACTION_WMM 17 /* WMM Specification 1.1 */
/* Public action codes (IEEE Std 802.11-2016, 9.6.8.1, Table 9-307) */
#define WLAN_PA_VENDOR_SPECIFIC 9
#define WLAN_PA_GAS_INITIAL_REQ 10
#define WLAN_PA_GAS_INITIAL_RESP 11
#define WLAN_PA_GAS_COMEBACK_REQ 12
#define WLAN_PA_GAS_COMEBACK_RESP 13
/* SA Query Action frame (IEEE 802.11w/D8.0, 7.4.9) */ /* SA Query Action frame (IEEE 802.11w/D8.0, 7.4.9) */
#define WLAN_SA_QUERY_REQUEST 0 #define WLAN_SA_QUERY_REQUEST 0
#define WLAN_SA_QUERY_RESPONSE 1 #define WLAN_SA_QUERY_RESPONSE 1
@ -274,6 +281,8 @@
#define WLAN_TIMEOUT_KEY_LIFETIME 2 #define WLAN_TIMEOUT_KEY_LIFETIME 2
#define WLAN_TIMEOUT_ASSOC_COMEBACK 3 #define WLAN_TIMEOUT_ASSOC_COMEBACK 3
#define OUI_WFA 0x506f9a
#define DPP_OUI_TYPE 0x1A
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma pack(push, 1) #pragma pack(push, 1)
@ -343,110 +352,37 @@ enum lci_req_subelem {
LCI_REQ_SUBELEM_MAX_AGE = 4, LCI_REQ_SUBELEM_MAX_AGE = 4,
}; };
struct ieee80211_mgmt { #ifdef ESP_SUPPLICANT
le16 frame_control; struct ieee80211_pa_vendor {
le16 duration; u8 oui[3];
u8 da[6]; u8 wfa_stype;
u8 sa[6]; u8 vendor_data[];
u8 bssid[6];
le16 seq_ctrl;
union {
struct {
le16 auth_alg;
le16 auth_transaction;
le16 status_code;
/* possibly followed by Challenge text */
u8 variable[0];
} STRUCT_PACKED auth;
struct {
le16 reason_code;
} STRUCT_PACKED deauth;
struct {
le16 capab_info;
le16 listen_interval;
/* followed by SSID and Supported rates */
u8 variable[0];
} STRUCT_PACKED assoc_req;
struct {
le16 capab_info;
le16 status_code;
le16 aid;
/* followed by Supported rates */
u8 variable[0];
} STRUCT_PACKED assoc_resp, reassoc_resp;
struct {
le16 capab_info;
le16 listen_interval;
u8 current_ap[6];
/* followed by SSID and Supported rates */
u8 variable[0];
} STRUCT_PACKED reassoc_req;
struct {
le16 reason_code;
} STRUCT_PACKED disassoc;
struct {
u8 timestamp[8];
le16 beacon_int;
le16 capab_info;
/* followed by some of SSID, Supported rates,
* FH Params, DS Params, CF Params, IBSS Params, TIM */
u8 variable[0];
} STRUCT_PACKED beacon;
struct {
/* only variable items: SSID, Supported rates */
u8 variable[0];
} STRUCT_PACKED probe_req;
struct {
u8 timestamp[8];
le16 beacon_int;
le16 capab_info;
/* followed by some of SSID, Supported rates,
* FH Params, DS Params, CF Params, IBSS Params */
u8 variable[0];
} STRUCT_PACKED probe_resp;
struct {
u8 category;
union {
struct {
u8 action_code;
u8 dialog_token;
u8 status_code;
u8 variable[0];
} STRUCT_PACKED wmm_action;
struct{
u8 action_code;
u8 element_id;
u8 length;
u8 switch_mode;
u8 new_chan;
u8 switch_count;
} STRUCT_PACKED chan_switch;
struct {
u8 action;
u8 sta_addr[ETH_ALEN];
u8 target_ap_addr[ETH_ALEN];
u8 variable[0]; /* FT Request */
} STRUCT_PACKED ft_action_req;
struct {
u8 action;
u8 sta_addr[ETH_ALEN];
u8 target_ap_addr[ETH_ALEN];
le16 status_code;
u8 variable[0]; /* FT Request */
} STRUCT_PACKED ft_action_resp;
struct {
u8 action;
u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
} STRUCT_PACKED sa_query_req;
struct {
u8 action; /* */
u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
} STRUCT_PACKED sa_query_resp;
} u;
} STRUCT_PACKED action;
} u;
} STRUCT_PACKED; } STRUCT_PACKED;
struct ieee80211_gas_resp {
u8 diag_token;
u16 status_code;
u16 comeback_delay;
u8 type;
u8 length;
u8 data[];
} STRUCT_PACKED;
struct ieee80211_public_action {
u8 action;
union {
struct ieee80211_pa_vendor pa_vendor_spec;
struct ieee80211_gas_resp pa_gas_resp;
} v;
} STRUCT_PACKED;
struct ieee80211_action {
u8 category;
union {
struct ieee80211_public_action public_action;
} u;
} STRUCT_PACKED;
#endif /* ESP_SUPPLICANT */
#define IEEE80211_MAX_MMPDU_SIZE 2304 #define IEEE80211_MAX_MMPDU_SIZE 2304
struct ieee80211_ht_capabilities { struct ieee80211_ht_capabilities {

View File

@ -0,0 +1,562 @@
/*
* wpa_supplicant - DPP
* Copyright (c) 2017, Qualcomm Atheros, Inc.
* Copyright (c) 2018-2019, The Linux Foundation
*
* This software may be distributed under the terms of the BSD license.
*/
#include "esp_dpp_i.h"
#include "esp_dpp.h"
#include "esp_wpa.h"
#include "esp_timer.h"
#include "esp_event.h"
#include "common/ieee802_11_defs.h"
static void *s_dpp_task_hdl = NULL;
static void *s_dpp_evt_queue = NULL;
static void *s_dpp_api_lock = NULL;
static bool s_dpp_auth_start;
static int s_dpp_auth_retries;
struct esp_dpp_context_t s_dpp_ctx;
#define REQUEST_ADD 1
#define REQUEST_CANCEL 0
#define DPP_API_LOCK() xSemaphoreTakeRecursive(s_dpp_api_lock, portMAX_DELAY)
#define DPP_API_UNLOCK() xSemaphoreGiveRecursive(s_dpp_api_lock)
struct action_rx_param {
u8 sa[ETH_ALEN];
u32 channel;
u32 frm_len;
u32 vendor_data_len;
struct ieee80211_action *action_frm;
};
int esp_dpp_post_evt(uint32_t evt_id, uint32_t data)
{
DPP_API_LOCK();
dpp_event_t *evt = os_zalloc(sizeof(dpp_event_t));
if (evt == NULL) {
DPP_API_UNLOCK();
return ESP_ERR_DPP_NO_MEM;
}
evt->id = evt_id;
evt->data = data;
if ( xQueueSend(s_dpp_evt_queue, &evt, 10 / portTICK_PERIOD_MS ) != pdPASS) {
DPP_API_UNLOCK();
os_free(evt);
return ESP_ERR_DPP_FAILURE;
}
DPP_API_UNLOCK();
return ESP_OK;
}
static void esp_dpp_call_cb(wifi_dpp_event_t evt, void *data)
{
s_dpp_ctx.dpp_event_cb(evt, data);
}
void esp_send_action_frame(uint8_t *dest_mac, const uint8_t *buf, uint32_t len,
uint8_t channel, uint32_t wait_time_ms)
{
mgmt_tx_req_t *req = os_zalloc(sizeof(*req) + len);;
req->ifx = ESP_IF_WIFI_STA;
req->subtype = WLAN_FC_STYPE_ACTION;
memcpy(req->dest_mac, dest_mac, ETH_ALEN);
req->no_ack = false;
req->data_len = len;
memcpy(req->data, buf, req->data_len);
wpa_printf(MSG_DEBUG, "DPP: Mgmt Tx - MAC:" MACSTR ", Channel-%d, WaitT-%d",
MAC2STR(dest_mac), channel, wait_time_ms);
if (ESP_OK != esp_wifi_mgmt_tx_req(REQUEST_ADD, channel, wait_time_ms, req)) {
wpa_printf(MSG_ERROR, "DPP: Failed to perfrm offchannel operation");
esp_dpp_call_cb(WIFI_DPP_FAIL, (void *)ESP_ERR_DPP_TX_FAILURE);
os_free(req);
return;
}
os_free(req);
}
static void esp_dpp_rx_auth_req(struct action_rx_param *rx_param, uint8_t *dpp_data)
{
size_t len = rx_param->vendor_data_len - 2;
const u8 *r_bootstrap, *i_bootstrap;
u16 r_bootstrap_len, i_bootstrap_len;
struct dpp_bootstrap_info *own_bi;
int rc;
wpa_printf(MSG_INFO, "DPP: Authentication Request from " MACSTR, MAC2STR(rx_param->sa));
r_bootstrap = dpp_get_attr(dpp_data, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
&r_bootstrap_len);
if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
wpa_printf(MSG_INFO, "DPP: Missing or invalid Responder Bootstrapping Key Hash attribute");
rc = ESP_ERR_DPP_INVALID_ATTR;
goto fail;
}
wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash", r_bootstrap, r_bootstrap_len);
i_bootstrap = dpp_get_attr(dpp_data, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
&i_bootstrap_len);
if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) {
wpa_printf(MSG_INFO, "DPP: Missing or invalid Initiator Bootstrapping Key Hash attribute");
rc = ESP_ERR_DPP_INVALID_ATTR;
goto fail;
}
wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash", i_bootstrap, i_bootstrap_len);
own_bi = dpp_bootstrap_get_id(s_dpp_ctx.dpp_global, s_dpp_ctx.id);
/* Try to find own and peer bootstrapping key matches based on the
* received hash values */
if (os_memcmp(own_bi->pubkey_hash, r_bootstrap, SHA256_MAC_LEN)) {
wpa_printf(MSG_INFO, "DPP: No matching own bootstrapping key found as responder - ignore message");
rc = ESP_ERR_DPP_INVALID_ATTR;
goto fail;
}
s_dpp_ctx.dpp_auth = dpp_auth_req_rx(NULL, DPP_CAPAB_ENROLLEE, 0, NULL,
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),
wpabuf_len(s_dpp_ctx.dpp_auth->resp_msg),
rx_param->channel, OFFCHAN_TX_WAIT_TIME);
return;
fail:
esp_dpp_call_cb(WIFI_DPP_FAIL, (void *)rc);
}
static void gas_query_req_tx(struct dpp_authentication *auth)
{
struct wpabuf *buf;
int supp_op_classes[] = {81, 0};
buf = dpp_build_conf_req_helper(auth, NULL, 0, NULL,
supp_op_classes);
if (!buf) {
wpa_printf(MSG_DEBUG, "DPP: No configuration request data available");
esp_dpp_call_cb(WIFI_DPP_FAIL, (void *)ESP_ERR_DPP_FAILURE);
return;
}
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),
auth->curr_chan, OFFCHAN_TX_WAIT_TIME);
}
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;
if (conf->ssid_len) {
os_memcpy(wifi_cfg->sta.ssid, conf->ssid, conf->ssid_len);
}
if (dpp_akm_legacy(conf->akm)) {
if (conf->passphrase[0])
os_memcpy(wifi_cfg->sta.password, conf->passphrase,
sizeof(wifi_cfg->sta.password));
if (conf->akm == DPP_AKM_PSK_SAE) {
wifi_cfg->sta.pmf_cfg.capable = true;
wifi_cfg->sta.pmf_cfg.required = true;
}
}
if (conf->connector) {
/* TODO: Save the Connector and consider using a command
* to fetch the value instead of sending an event with
* it. The Connector could end up being larger than what
* most clients are ready to receive as an event
* message. */
wpa_printf(MSG_INFO, DPP_EVENT_CONNECTOR "%s",
conf->connector);
}
s_dpp_auth_start = false;
esp_wifi_mgmt_tx_req(REQUEST_CANCEL, 0, 0, NULL);
esp_dpp_call_cb(WIFI_DPP_CFG_RECVD, wifi_cfg);
return 0;
}
static void esp_dpp_rx_auth_conf(struct action_rx_param *rx_param, uint8_t *dpp_data)
{
struct dpp_authentication *auth = s_dpp_ctx.dpp_auth;
struct ieee80211_public_action *public_action =
&rx_param->action_frm->u.public_action;
size_t len = rx_param->vendor_data_len - 2;
int rc;
wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation from " MACSTR,
MAC2STR(rx_param->sa));
if (!auth) {
wpa_printf(MSG_DEBUG, "DPP: No DPP Authentication in progress - drop");
rc = ESP_ERR_DPP_FAILURE;
goto fail;
}
if (os_memcmp(rx_param->sa, auth->peer_mac_addr, ETH_ALEN) != 0) {
wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
rc = ESP_ERR_DPP_FAILURE;
goto fail;
}
if (dpp_auth_conf_rx(auth, (const u8 *)&public_action->v,
dpp_data, len) < 0) {
wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
rc = ESP_ERR_DPP_FAILURE;
goto fail;
}
/* Send GAS Query Req */
gas_query_req_tx(auth);
return;
fail:
esp_dpp_call_cb(WIFI_DPP_FAIL, (void *)rc);
}
static void esp_dpp_rx_auth(struct action_rx_param *rx_param)
{
uint8_t crypto_suit, type;
uint8_t *tmp;
tmp = rx_param->action_frm->u.public_action.v.pa_vendor_spec.vendor_data;
crypto_suit = tmp[0];
type = tmp[1];
if (crypto_suit != 1) {
wpa_printf(MSG_ERROR, "DPP: Unsupported crypto suit");
esp_dpp_call_cb(WIFI_DPP_FAIL, (void *)ESP_ERR_DPP_NOT_SUPPORTED);
return;
}
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;
}
}
static void gas_query_resp_rx(struct action_rx_param *rx_param)
{
struct dpp_authentication *auth = s_dpp_ctx.dpp_auth;
uint8_t *pos = rx_param->action_frm->u.public_action.v.pa_gas_resp.data;
uint8_t *resp = &pos[10];
int i, res;
if (pos[1] == WLAN_EID_VENDOR_SPECIFIC && pos[2] == 5 &&
WPA_GET_BE24(&pos[3]) == OUI_WFA && pos[6] == 0x1a && pos[7] == 1) {
if (dpp_conf_resp_rx(auth, resp, rx_param->vendor_data_len-2) < 0) {
wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
goto fail;
}
for (i = 0; i < auth->num_conf_obj; i++) {
res = esp_dpp_handle_config_obj(auth, &auth->conf_obj[i]);
if (res < 0)
goto fail;
}
}
return;
fail:
esp_dpp_call_cb(WIFI_DPP_FAIL, (void *)ESP_ERR_DPP_FAILURE);
}
static void esp_dpp_rx_action(struct action_rx_param *rx_param)
{
if (rx_param->action_frm->category == WLAN_ACTION_PUBLIC) {
struct ieee80211_public_action *public_action =
&rx_param->action_frm->u.public_action;
wpa_printf(MSG_DEBUG, "DPP: Rx Public Action frame: action - %d",
public_action->action);
if (public_action->action == WLAN_PA_VENDOR_SPECIFIC &&
WPA_GET_BE24(public_action->v.pa_vendor_spec.oui) == OUI_WFA &&
public_action->v.pa_vendor_spec.wfa_stype == DPP_OUI_TYPE) {
rx_param->vendor_data_len = rx_param->frm_len -
(size_t)(public_action->v.pa_vendor_spec.vendor_data -
(u8 *)rx_param->action_frm);
if (!s_dpp_auth_start) {
s_dpp_auth_start = true;
esp_dpp_stop_listen();
}
esp_dpp_rx_auth(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 &&
public_action->v.pa_gas_resp.status_code == 0) {
rx_param->vendor_data_len = rx_param->frm_len -
(size_t)(public_action->v.pa_gas_resp.data +
public_action->v.pa_gas_resp.length -
(u8 *)rx_param->action_frm);
gas_query_resp_rx(rx_param);
}
}
os_free(rx_param->action_frm);
os_free(rx_param);
}
void esp_dpp_task(void *pvParameters )
{
dpp_event_t *evt;
bool task_del = false;
for (;;) {
if (xQueueReceive(s_dpp_evt_queue, &evt, portMAX_DELAY) == pdTRUE) {
if (evt->id < SIG_DPP_MAX) {
DPP_API_LOCK();
} else {
os_free(evt);
continue;
}
switch (evt->id) {
case SIG_DPP_DEL_TASK:
task_del = true;
break;
case SIG_DPP_BOOTSTRAP_GEN:
{
char *command = (char *)evt->data;
const char *uri;
s_dpp_ctx.id = dpp_bootstrap_gen(s_dpp_ctx.dpp_global, command);
uri = dpp_bootstrap_get_uri(s_dpp_ctx.dpp_global, s_dpp_ctx.id);
esp_dpp_call_cb(WIFI_DPP_URI_READY, (void *)uri);
os_free(command);
}
break;
case SIG_DPP_RX_ACTION:
{
esp_dpp_rx_action((struct action_rx_param *)evt->data);
}
break;
default:
break;
}
os_free(evt);
DPP_API_UNLOCK();
if (task_del)
break;
}
}
vQueueDelete(s_dpp_evt_queue);
s_dpp_evt_queue = NULL;
if (s_dpp_api_lock) {
vSemaphoreDelete(s_dpp_api_lock);
s_dpp_api_lock = NULL;
}
/* At this point, we completed */
vTaskDelete(NULL);
}
int esp_dpp_rx_mgmt(uint8_t *hdr, uint8_t *payload, size_t len, uint8_t channel)
{
struct ieee80211_hdr *rx_hdr = (struct ieee80211_hdr *)hdr;
struct action_rx_param *rx_param;
if (WLAN_FC_GET_STYPE(rx_hdr->frame_control) == WLAN_FC_STYPE_ACTION) {
rx_param = os_zalloc(sizeof(struct action_rx_param));
os_memcpy(rx_param->sa, rx_hdr->addr2, ETH_ALEN);
rx_param->channel = channel;
rx_param->action_frm = os_zalloc(len);
rx_param->frm_len = len;
os_memcpy(rx_param->action_frm, payload, len);
if (ESP_OK != esp_dpp_post_evt(SIG_DPP_RX_ACTION, (u32)rx_param)) {
os_free(rx_param->action_frm);
os_free(rx_param);
}
}
return ESP_ERR_NOT_SUPPORTED;
}
static void offchan_event_handler(void* arg, esp_event_base_t event_base,
int event_id, void* event_data)
{
if (event_id == WIFI_EVENT_MGMT_TX_STATUS) {
wifi_event_mgmt_tx_status_t *evt =
(wifi_event_mgmt_tx_status_t *)event_data;
wpa_printf(MSG_DEBUG, "Mgmt Tx Status - %d, Cookie - 0x%x",
evt->status, (uint32_t)evt->cookie);
if (evt->status)
esp_dpp_call_cb(WIFI_DPP_FAIL, (void *)ESP_ERR_DPP_TX_FAILURE);
} else if (event_id == WIFI_EVENT_ROC_DONE) {
wifi_event_roc_done_t *evt = (wifi_event_roc_done_t *)event_data;
if (!s_dpp_auth_start && evt->cookie == BOOTSTRAP_ROC_COOKIE) {
esp_wifi_remain_on_channel(ESP_IF_WIFI_STA, REQUEST_ADD,
s_dpp_ctx.bootstrap_params.channel,
BOOTSTRAP_ROC_WAIT_TIME,
(void *)BOOTSTRAP_ROC_COOKIE);
}
}
}
esp_err_t esp_dpp_bootstrap_gen(uint8_t channel, enum dpp_bootstrap_type type,
const char *key, const char *uri_info)
{
struct dpp_bootstrap_params_t *params = &s_dpp_ctx.bootstrap_params;
char *command = os_zalloc(1200);
int ret;
if (type != DPP_BOOTSTRAP_QR_CODE) {
wpa_printf(MSG_INFO, "Bootstrap type %d not supported", type);
os_free(command);
ret = ESP_ERR_DPP_NOT_SUPPORTED;
goto fail;
}
params->type = type;
params->channel = channel;
esp_wifi_get_mac(ESP_IF_WIFI_STA, params->mac);
if (uri_info) {
params->info_len = strlen(uri_info);
if (params->info_len) {
params->info = os_zalloc(params->info_len+1);
if (!params->info) {
ret = ESP_ERR_DPP_NO_MEM;
goto fail;
}
os_memcpy(params->info, uri_info, params->info_len);
}
}
if (key) {
params->key_len = strlen(key);
if (params->key_len) {
char prefix[] = "30310201010420";
char postfix[] = "a00a06082a8648ce3d030107";
params->key = os_zalloc(params->key_len +
sizeof(prefix) + sizeof(postfix));
if (!params->key) {
ret = ESP_ERR_DPP_NO_MEM;
goto fail;
}
sprintf(params->key, "%s%s%s", prefix, key, postfix);
}
}
sprintf(command, "type=qrcode mac=" MACSTR " chan=81/%d %s%s%s%s",
MAC2STR(params->mac), channel,
params->key_len ? "key=" : "",
params->key_len ? params->key : "",
params->info_len ? " info=" : "",
params->info_len ? params->info : "");
ret = esp_dpp_post_evt(SIG_DPP_BOOTSTRAP_GEN, (u32)command);
if (ret != ESP_OK) {
os_free(command);
if (params->info) {
os_free(params->info);
params->info = NULL;
}
if (params->key) {
os_free(params->key);
params->key = NULL;
}
goto fail;
}
return ESP_OK;
fail:
return ret;
}
void esp_dpp_start_listen(uint8_t channel)
{
esp_wifi_remain_on_channel(ESP_IF_WIFI_STA, REQUEST_ADD, channel,
BOOTSTRAP_ROC_WAIT_TIME, (void *)BOOTSTRAP_ROC_COOKIE);
}
void esp_dpp_stop_listen(void)
{
esp_wifi_remain_on_channel(ESP_IF_WIFI_STA, REQUEST_CANCEL, 0, 0, NULL);
}
esp_err_t esp_supp_dpp_init(wifi_dpp_event_cb_t cb)
{
struct dpp_global_config cfg = {0};
os_bzero(&s_dpp_ctx, sizeof(s_dpp_ctx));
s_dpp_ctx.dpp_event_cb = cb;
cfg.cb_ctx = &s_dpp_ctx;
cfg.msg_ctx = &s_dpp_ctx;
s_dpp_ctx.dpp_global = dpp_global_init(&cfg);
s_dpp_auth_start = false;
s_dpp_evt_queue = xQueueCreate(3, sizeof(dpp_event_t));
xTaskCreate(esp_dpp_task, "dppT", DPP_TASK_STACK_SIZE, NULL, 2, s_dpp_task_hdl);
s_dpp_api_lock = xSemaphoreCreateRecursiveMutex();
if (!s_dpp_api_lock) {
wpa_printf(MSG_ERROR, "DPP: dpp_init: failed to create DPP API lock");
return ESP_ERR_DPP_NO_MEM;
}
esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_MGMT_TX_STATUS,
&offchan_event_handler, NULL);
esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_ROC_DONE,
&offchan_event_handler, NULL);
wpa_printf(MSG_INFO, "esp_dpp_task prio:%d, stack:%d\n", 2, DPP_TASK_STACK_SIZE);
return ESP_OK;
}
void esp_supp_dpp_deinit(void)
{
struct dpp_bootstrap_params_t *params = &s_dpp_ctx.bootstrap_params;
if (params->info) {
os_free(params->info);
params->info = NULL;
}
if (params->key) {
os_free(params->key);
params->key = NULL;
}
s_dpp_auth_retries = 0;
dpp_global_deinit(s_dpp_ctx.dpp_global);
esp_dpp_post_evt(SIG_DPP_DEL_TASK, 0);
}

View File

@ -0,0 +1,69 @@
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ESP_DPP_I_H
#define ESP_DPP_I_H
#include "esp_err.h"
#include "utils/includes.h"
#include "utils/common.h"
#include "common/dpp.h"
#include "esp_dpp.h"
#include "esp_wifi_driver.h"
#define DPP_TASK_STACK_SIZE (6144 + TASK_STACK_SIZE_ADD)
enum SIG_DPP {
SIG_DPP_RESET = 0,
SIG_DPP_BOOTSTRAP_GEN,
SIG_DPP_RX_ACTION,
SIG_DPP_DEL_TASK,
SIG_DPP_MAX,
};
typedef struct {
uint32_t id;
uint32_t data;
} dpp_event_t;
#define BOOTSTRAP_ROC_WAIT_TIME 5000
#define OFFCHAN_TX_WAIT_TIME 500
#define BOOTSTRAP_ROC_COOKIE 0xABABABAB
struct dpp_bootstrap_params_t {
enum dpp_bootstrap_type type;
uint8_t channel;
uint8_t mac[6];
uint32_t key_len;
char *key;
uint32_t info_len;
char *info;
};
struct esp_dpp_context_t {
struct dpp_bootstrap_params_t bootstrap_params;
struct dpp_authentication *dpp_auth;
int gas_dialog_token;
wifi_config_t wifi_config;
wifi_dpp_event_cb_t dpp_event_cb;
struct dpp_global *dpp_global;
wifi_config_t wifi_cfg;
int id;
};
int esp_dpp_rx_mgmt(uint8_t *hdr, uint8_t *payload, size_t len, uint8_t channel);
#endif /* ESP_DPP_I_H */

View File

@ -36,6 +36,7 @@
#include "esp_wpa3_i.h" #include "esp_wpa3_i.h"
#include "esp_wpa2.h" #include "esp_wpa2.h"
#include "esp_common_i.h" #include "esp_common_i.h"
#include "esp_dpp_i.h"
void wpa_install_key(enum wpa_alg alg, u8 *addr, int key_idx, int set_tx, void wpa_install_key(enum wpa_alg alg, u8 *addr, int key_idx, int set_tx,
u8 *seq, size_t seq_len, u8 *key, size_t key_len, int key_entry_valid) u8 *seq, size_t seq_len, u8 *key, size_t key_len, int key_entry_valid)
@ -253,6 +254,7 @@ int esp_supplicant_init(void)
wpa_cb->wpa_parse_wpa_ie = wpa_parse_wpa_ie_wrapper; wpa_cb->wpa_parse_wpa_ie = wpa_parse_wpa_ie_wrapper;
wpa_cb->wpa_config_bss = NULL;//wpa_config_bss; wpa_cb->wpa_config_bss = NULL;//wpa_config_bss;
wpa_cb->wpa_michael_mic_failure = wpa_michael_mic_failure; wpa_cb->wpa_michael_mic_failure = wpa_michael_mic_failure;
wpa_cb->offchan_rx_mgmt = esp_dpp_rx_mgmt;
esp_wifi_register_wpa3_cb(wpa_cb); esp_wifi_register_wpa3_cb(wpa_cb);
esp_supplicant_common_init(wpa_cb); esp_supplicant_common_init(wpa_cb);