net: wifi_mgmt: add hostap DPP support

Add wifi l2 mgmt dpp handlers.
Add wifi subcommand dpp to call l2 mgmt dpp handlers.

DPP l2 handlers will parse params to hostap wpa_cli format args
and send wpa_cli commands to hostap.

Signed-off-by: Fengming Ye <frank.ye@nxp.com>
This commit is contained in:
Fengming Ye 2024-06-04 17:23:58 +09:00 committed by Anas Nashif
parent 37491cb0f7
commit 1640826fc5
5 changed files with 486 additions and 0 deletions

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2017 Intel Corporation.
* Copyright 2024 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -91,6 +92,8 @@ enum net_request_wifi_cmd {
NET_REQUEST_WIFI_CMD_RTS_THRESHOLD,
/** Configure AP parameter */
NET_REQUEST_WIFI_CMD_AP_CONFIG_PARAM,
/** DPP actions */
NET_REQUEST_WIFI_CMD_DPP,
/** @cond INTERNAL_HIDDEN */
NET_REQUEST_WIFI_CMD_MAX
/** @endcond */
@ -198,6 +201,12 @@ NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_RTS_THRESHOLD);
NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_AP_CONFIG_PARAM);
/** Request a Wi-Fi DPP operation */
#define NET_REQUEST_WIFI_DPP \
(_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_DPP)
NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_DPP);
/** @brief Wi-Fi management events */
enum net_event_wifi_cmd {
/** Scan results available */
@ -768,6 +777,178 @@ struct wifi_ap_config_params {
uint32_t max_num_sta;
};
/** @brief Wi-Fi DPP configuration parameter */
/** Wi-Fi DPP QR-CODE in string max len for SHA512 */
#define WIFI_DPP_QRCODE_MAX_LEN 255
/** Wi-Fi DPP operations */
enum wifi_dpp_op {
/** Unset invalid operation */
WIFI_DPP_OP_INVALID = 0,
/** Add configurator */
WIFI_DPP_CONFIGURATOR_ADD,
/** Start DPP auth as configurator or enrollee */
WIFI_DPP_AUTH_INIT,
/** Scan qr_code as parameter */
WIFI_DPP_QR_CODE,
/** Start DPP chirp to send DPP announcement */
WIFI_DPP_CHIRP,
/** Listen on specific frequency */
WIFI_DPP_LISTEN,
/** Generate a bootstrap like qrcode */
WIFI_DPP_BOOTSTRAP_GEN,
/** Get a bootstrap uri for external device to scan */
WIFI_DPP_BOOTSTRAP_GET_URI,
/** Set configurator parameters */
WIFI_DPP_SET_CONF_PARAM,
/** Set DPP rx response wait timeout */
WIFI_DPP_SET_WAIT_RESP_TIME
};
/** Wi-Fi DPP crypto Elliptic Curves */
enum wifi_dpp_curves {
/** Unset default use P-256 */
WIFI_DPP_CURVES_DEFAULT = 0,
/** prime256v1 */
WIFI_DPP_CURVES_P_256,
/** secp384r1 */
WIFI_DPP_CURVES_P_384,
/** secp521r1 */
WIFI_DPP_CURVES_P_512,
/** brainpoolP256r1 */
WIFI_DPP_CURVES_BP_256,
/** brainpoolP384r1 */
WIFI_DPP_CURVES_BP_384,
/** brainpoolP512r1 */
WIFI_DPP_CURVES_BP_512
};
/** Wi-Fi DPP role */
enum wifi_dpp_role {
/** Unset role */
WIFI_DPP_ROLE_UNSET = 0,
/** Configurator passes AP config to enrollee */
WIFI_DPP_ROLE_CONFIGURATOR,
/** Enrollee gets AP config and connect to AP */
WIFI_DPP_ROLE_ENROLLEE,
/** Both configurator and enrollee might be chosen */
WIFI_DPP_ROLE_EITHER
};
/** Wi-Fi DPP security type
*
* current only support DPP only AKM
*/
enum wifi_dpp_conf {
/** Unset conf */
WIFI_DPP_CONF_UNSET = 0,
/** conf=sta-dpp, AKM DPP only for sta */
WIFI_DPP_CONF_STA,
/** conf=ap-dpp, AKM DPP only for ap */
WIFI_DPP_CONF_AP,
/** conf=query, query for AKM */
WIFI_DPP_CONF_QUERY
};
/** Wi-Fi DPP bootstrap type
*
* current default and only support QR-CODE
*/
enum wifi_dpp_bootstrap_type {
/** Unset type */
WIFI_DPP_BOOTSTRAP_TYPE_UNSET = 0,
/** qrcode */
WIFI_DPP_BOOTSTRAP_TYPE_QRCODE,
/** pkex */
WIFI_DPP_BOOTSTRAP_TYPE_PKEX,
/** nfc */
WIFI_DPP_BOOTSTRAP_TYPE_NFC_URI
};
/** Wi-Fi DPP params for various operations
*/
struct wifi_dpp_params {
/** Operation enum */
int action;
union {
/** Params to add DPP configurator */
struct wifi_dpp_configurator_add_params {
/** ECP curves for private key */
int curve;
/** ECP curves for net access key */
int net_access_key_curve;
} configurator_add;
/** Params to initiate a DPP auth procedure */
struct wifi_dpp_auth_init_params {
/** Peer bootstrap id */
int peer;
/** Configuration parameter id */
int configurator;
/** Role configurator or enrollee */
int role;
/** Security type */
int conf;
/** SSID in string */
char ssid[WIFI_SSID_MAX_LEN + 1];
} auth_init;
/** Params to do DPP chirp */
struct wifi_dpp_chirp_params {
/** Own bootstrap id */
int id;
/** Chirp on frequency */
int freq;
} chirp;
/** Params to do DPP listen */
struct wifi_dpp_listen_params {
/** Listen on frequency */
int freq;
/** Role configurator or enrollee */
int role;
} listen;
/** Params to generate a DPP bootstrap */
struct wifi_dpp_bootstrap_gen_params {
/** Bootstrap type */
int type;
/** Own operating class */
int op_class;
/** Own working channel */
int chan;
/** ECP curves */
int curve;
/** Own mac address */
uint8_t mac[WIFI_MAC_ADDR_LEN];
} bootstrap_gen;
/** Params to set specific DPP configurator */
struct wifi_dpp_configurator_set_params {
/** Peer bootstrap id */
int peer;
/** Configuration parameter id */
int configurator;
/** Role configurator or enrollee */
int role;
/** Security type */
int conf;
/** ECP curves for private key */
int curve;
/** ECP curves for net access key */
int net_access_key_curve;
/** Own mac address */
char ssid[WIFI_SSID_MAX_LEN + 1];
} configurator_set;
/** Bootstrap get uri id */
int id;
/** Timeout for DPP frame response rx */
int dpp_resp_wait_time;
/** DPP QR-CODE, max for SHA512 */
uint8_t dpp_qr_code[WIFI_DPP_QRCODE_MAX_LEN + 1];
/** Request response reusing request buffer.
* So once a request is sent, buffer will be
* fulfilled by response
*/
char resp[WIFI_DPP_QRCODE_MAX_LEN + 1];
};
};
#include <zephyr/net/net_if.h>
/** Scan result callback
@ -956,6 +1137,14 @@ struct wifi_mgmt_ops {
* @return 0 if ok, < 0 if error
*/
int (*ap_config_params)(const struct device *dev, struct wifi_ap_config_params *params);
/** Dispatch DPP operations by action enum, with or without arguments in string format
*
* @param dev Pointer to the device structure for the driver instance
* @param params DPP action enum and parameters in string
*
* @return 0 if ok, < 0 if error
*/
int (*dpp_dispatch)(const struct device *dev, struct wifi_dpp_params *params);
};
/** Wi-Fi management offload API */

View file

@ -1,5 +1,6 @@
/**
* Copyright (c) 2023 Nordic Semiconductor ASA
* Copyright 2024 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -1024,3 +1025,269 @@ out:
return ret;
}
#endif /* CONFIG_AP */
static const char *dpp_params_to_args_curve(int curve)
{
switch (curve) {
case WIFI_DPP_CURVES_P_256:
return "P-256";
case WIFI_DPP_CURVES_P_384:
return "P-384";
case WIFI_DPP_CURVES_P_512:
return "P-521";
case WIFI_DPP_CURVES_BP_256:
return "BP-256";
case WIFI_DPP_CURVES_BP_384:
return "BP-384";
case WIFI_DPP_CURVES_BP_512:
return "BP-512";
default:
return "P-256";
}
}
static const char *dpp_params_to_args_conf(int conf)
{
switch (conf) {
case WIFI_DPP_CONF_STA:
return "sta-dpp";
case WIFI_DPP_CONF_AP:
return "ap-dpp";
case WIFI_DPP_CONF_QUERY:
return "query";
default:
return "sta-dpp";
}
}
static const char *dpp_params_to_args_role(int role)
{
switch (role) {
case WIFI_DPP_ROLE_CONFIGURATOR:
return "configurator";
case WIFI_DPP_ROLE_ENROLLEE:
return "enrollee";
case WIFI_DPP_ROLE_EITHER:
return "either";
default:
return "either";
}
}
static void dpp_ssid_bin2str(char *dst, uint8_t *src, int max_len)
{
uint8_t *end = src + strlen(src);
/* do 4 bytes convert first */
for (; (src + 4) < end; src += 4) {
snprintf(dst, max_len, "%02x%02x%02x%02x",
src[0], src[1], src[2], src[3]);
dst += 8;
}
/* then do 1 byte convert */
for (; src < end; src++) {
snprintf(dst, max_len, "%02x", src[0]);
dst += 2;
}
}
#define SUPPLICANT_DPP_CMD_BUF_SIZE 384
#define STR_CUR_TO_END(cur) (cur) = (&(cur)[0] + strlen((cur)))
int supplicant_dpp_dispatch(const struct device *dev,
struct wifi_dpp_params *params)
{
char *pos;
static char dpp_cmd_buf[SUPPLICANT_DPP_CMD_BUF_SIZE] = {0};
char *end = &dpp_cmd_buf[SUPPLICANT_DPP_CMD_BUF_SIZE - 2];
memset(dpp_cmd_buf, 0x0, SUPPLICANT_DPP_CMD_BUF_SIZE);
pos = &dpp_cmd_buf[0];
switch (params->action) {
case WIFI_DPP_CONFIGURATOR_ADD:
strncpy(pos, "DPP_CONFIGURATOR_ADD", end - pos);
STR_CUR_TO_END(pos);
if (params->configurator_add.curve) {
snprintf(pos, end - pos, " curve=%s",
dpp_params_to_args_curve(params->configurator_add.curve));
STR_CUR_TO_END(pos);
}
if (params->configurator_add.net_access_key_curve) {
snprintf(pos, end - pos, " net_access_key_curve=%s",
dpp_params_to_args_curve(
params->configurator_add.net_access_key_curve));
}
break;
case WIFI_DPP_AUTH_INIT:
strncpy(pos, "DPP_AUTH_INIT", end - pos);
STR_CUR_TO_END(pos);
if (params->auth_init.peer) {
snprintf(pos, end - pos, " peer=%d", params->auth_init.peer);
STR_CUR_TO_END(pos);
}
if (params->auth_init.conf) {
snprintf(pos, end - pos, " conf=%s",
dpp_params_to_args_conf(
params->auth_init.conf));
STR_CUR_TO_END(pos);
}
if (params->auth_init.ssid[0]) {
strncpy(pos, " ssid=", end - pos);
STR_CUR_TO_END(pos);
dpp_ssid_bin2str(pos, params->auth_init.ssid,
WIFI_SSID_MAX_LEN * 2);
STR_CUR_TO_END(pos);
}
if (params->auth_init.configurator) {
snprintf(pos, end - pos, " configurator=%d",
params->auth_init.configurator);
STR_CUR_TO_END(pos);
}
if (params->auth_init.role) {
snprintf(pos, end - pos, " role=%s",
dpp_params_to_args_role(
params->auth_init.role));
}
break;
case WIFI_DPP_QR_CODE:
strncpy(pos, "DPP_QR_CODE", end - pos);
STR_CUR_TO_END(pos);
if (params->dpp_qr_code[0]) {
snprintf(pos, end - pos, " %s", params->dpp_qr_code);
}
break;
case WIFI_DPP_CHIRP:
strncpy(pos, "DPP_CHIRP", end - pos);
STR_CUR_TO_END(pos);
if (params->chirp.id) {
snprintf(pos, end - pos, " own=%d", params->chirp.id);
STR_CUR_TO_END(pos);
}
if (params->chirp.freq) {
snprintf(pos, end - pos, " listen=%d", params->chirp.freq);
}
break;
case WIFI_DPP_LISTEN:
strncpy(pos, "DPP_LISTEN", end - pos);
STR_CUR_TO_END(pos);
if (params->listen.freq) {
snprintf(pos, end - pos, " %d", params->listen.freq);
STR_CUR_TO_END(pos);
}
if (params->listen.role) {
snprintf(pos, end - pos, " role=%s",
dpp_params_to_args_role(
params->listen.role));
}
break;
case WIFI_DPP_BOOTSTRAP_GEN:
strncpy(pos, "DPP_BOOTSTRAP_GEN", end - pos);
STR_CUR_TO_END(pos);
if (params->bootstrap_gen.type) {
strncpy(pos, " type=qrcode", end - pos);
STR_CUR_TO_END(pos);
}
if (params->bootstrap_gen.op_class &&
params->bootstrap_gen.chan) {
snprintf(pos, end - pos, " chan=%d/%d",
params->bootstrap_gen.op_class,
params->bootstrap_gen.chan);
STR_CUR_TO_END(pos);
}
/* mac is mandatory, even if it is zero mac address */
snprintf(pos, end - pos, " mac=%02x:%02x:%02x:%02x:%02x:%02x",
params->bootstrap_gen.mac[0], params->bootstrap_gen.mac[1],
params->bootstrap_gen.mac[2], params->bootstrap_gen.mac[3],
params->bootstrap_gen.mac[4], params->bootstrap_gen.mac[5]);
STR_CUR_TO_END(pos);
if (params->bootstrap_gen.curve) {
snprintf(pos, end - pos, " curve=%s",
dpp_params_to_args_curve(params->bootstrap_gen.curve));
}
break;
case WIFI_DPP_BOOTSTRAP_GET_URI:
snprintf(pos, end - pos, "DPP_BOOTSTRAP_GET_URI %d", params->id);
break;
case WIFI_DPP_SET_CONF_PARAM:
strncpy(pos, "SET dpp_configurator_params", end - pos);
STR_CUR_TO_END(pos);
if (params->configurator_set.peer) {
snprintf(pos, end - pos, " peer=%d", params->configurator_set.peer);
STR_CUR_TO_END(pos);
}
if (params->configurator_set.conf) {
snprintf(pos, end - pos, " conf=%s",
dpp_params_to_args_conf(
params->configurator_set.conf));
STR_CUR_TO_END(pos);
}
if (params->configurator_set.ssid[0]) {
strncpy(pos, " ssid=", end - pos);
STR_CUR_TO_END(pos);
dpp_ssid_bin2str(pos, params->configurator_set.ssid,
WIFI_SSID_MAX_LEN * 2);
STR_CUR_TO_END(pos);
}
if (params->configurator_set.configurator) {
snprintf(pos, end - pos, " configurator=%d",
params->configurator_set.configurator);
STR_CUR_TO_END(pos);
}
if (params->configurator_set.role) {
snprintf(pos, end - pos, " role=%s",
dpp_params_to_args_role(
params->configurator_set.role));
STR_CUR_TO_END(pos);
}
if (params->configurator_set.curve) {
snprintf(pos, end - pos, " curve=%s",
dpp_params_to_args_curve(params->configurator_set.curve));
STR_CUR_TO_END(pos);
}
if (params->configurator_set.net_access_key_curve) {
snprintf(pos, end - pos, " net_access_key_curve=%s",
dpp_params_to_args_curve(
params->configurator_set.net_access_key_curve));
}
break;
case WIFI_DPP_SET_WAIT_RESP_TIME:
snprintf(pos, end - pos, "SET dpp_resp_wait_time %d",
params->dpp_resp_wait_time);
break;
default:
wpa_printf(MSG_ERROR, "Unknown DPP action");
return -1;
}
wpa_printf(MSG_DEBUG, "%s", dpp_cmd_buf);
if (zephyr_wpa_cli_cmd_resp(dpp_cmd_buf, params->resp)) {
return -1;
}
return 0;
}

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2023 Nordic Semiconductor ASA
* Copyright 2024 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -175,4 +176,14 @@ int supplicant_ap_sta_disconnect(const struct device *dev,
const uint8_t *mac_addr);
#endif /* CONFIG_AP */
/**
* @brief Dispatch DPP operations
*
* @param dev Wi-Fi interface name to use
* @param dpp_params DPP action enum and params in string
* @return 0 for OK; -1 for ERROR
*/
int supplicant_dpp_dispatch(const struct device *dev,
struct wifi_dpp_params *params);
#endif /* ZEPHYR_SUPP_MGMT_H */

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2023 Nordic Semiconductor ASA.
* Copyright 2024 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -65,6 +66,7 @@ static const struct wifi_mgmt_ops mgmt_ops = {
.ap_disable = supplicant_ap_disable,
.ap_sta_disconnect = supplicant_ap_sta_disconnect,
#endif /* CONFIG_AP */
.dpp_dispatch = supplicant_dpp_dispatch,
};
DEFINE_WIFI_NM_INSTANCE(wifi_supplicant, &mgmt_ops);

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2016 Intel Corporation.
* Copyright 2024 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -788,6 +789,22 @@ static int wifi_set_rts_threshold(uint32_t mgmt_request, struct net_if *iface,
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_RTS_THRESHOLD, wifi_set_rts_threshold);
static int wifi_dpp(uint32_t mgmt_request, struct net_if *iface,
void *data, size_t len)
{
const struct device *dev = net_if_get_device(iface);
const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
struct wifi_dpp_params *params = data;
if (wifi_mgmt_api == NULL || wifi_mgmt_api->dpp_dispatch == NULL) {
return -ENOTSUP;
}
return wifi_mgmt_api->dpp_dispatch(dev, params);
}
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_DPP, wifi_dpp);
#ifdef CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS
void wifi_mgmt_raise_raw_scan_result_event(struct net_if *iface,
struct wifi_raw_scan_result *raw_scan_result)