Skip to content

Commit

Permalink
hostap: add WPA2 EAP_TLS support
Browse files Browse the repository at this point in the history
Add basic wpa2 EAP_TLS support.
Support set CA/client cert and client key.

Signed-off-by: Maochen Wang <maochen.wang@nxp.com>
  • Loading branch information
MaochenWang1 committed Jul 24, 2024
1 parent c0b464c commit 5f9de8e
Show file tree
Hide file tree
Showing 7 changed files with 212 additions and 7 deletions.
8 changes: 6 additions & 2 deletions include/zephyr/net/wifi.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,14 @@ enum wifi_security_type {
WIFI_SECURITY_TYPE_SAE,
/** GB 15629.11-2003 WAPI security. */
WIFI_SECURITY_TYPE_WAPI,
/** EAP security - Enterprise. */
WIFI_SECURITY_TYPE_EAP,
/** WEP security. */
WIFI_SECURITY_TYPE_WEP,
/** WPA-PSK security. */
WIFI_SECURITY_TYPE_WPA_PSK,
/** WPA/WPA2/WPA3 PSK security. */
WIFI_SECURITY_TYPE_WPA_AUTO_PERSONAL,
/** EAP TLS security - Enterprise. */
WIFI_SECURITY_TYPE_EAP_TLS,

/** @cond INTERNAL_HIDDEN */
__WIFI_SECURITY_TYPE_AFTER_LAST,
Expand Down Expand Up @@ -118,6 +118,10 @@ const char *wifi_band_txt(enum wifi_frequency_bands band);
#define WIFI_SAE_PSWD_MAX_LEN 128
/** MAC address length */
#define WIFI_MAC_ADDR_LEN 6
/** Max identity length */
#define WIFI_IDENTITY_MAX_LEN 64
/** Max password length */
#define WIFI_PSWD_MAX_LEN 128

/** Minimum channel number */
#define WIFI_CHANNEL_MIN 1
Expand Down
24 changes: 24 additions & 0 deletions include/zephyr/net/wifi_mgmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ enum net_request_wifi_cmd {
NET_REQUEST_WIFI_CMD_AP_CONFIG_PARAM,
/** Flush PMKSA cache entries */
NET_REQUEST_WIFI_CMD_PMKSA_FLUSH,
/** Set enterprise mode file */
NET_REQUEST_WIFI_CMD_ENTERPRISE_FILE,
/** @cond INTERNAL_HIDDEN */
NET_REQUEST_WIFI_CMD_MAX
/** @endcond */
Expand Down Expand Up @@ -214,6 +216,12 @@ NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_AP_CONFIG_PARAM);

NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_PMKSA_FLUSH);

/** Set Wi-Fi enterprise mode CA/client Cert and key file */
#define NET_REQUEST_WIFI_ENTERPRISE_FILE \
(_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_ENTERPRISE_FILE)

NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_ENTERPRISE_FILE);

/** @brief Wi-Fi management events */
enum net_event_wifi_cmd {
/** Scan results available */
Expand Down Expand Up @@ -418,6 +426,14 @@ struct wifi_connect_req_params {
uint8_t bssid[WIFI_MAC_ADDR_LEN];
/** Connect timeout in seconds, SYS_FOREVER_MS for no timeout */
int timeout;
/** anonymous identity */
const uint8_t *anon_id;
/** anon_id length */
uint8_t aid_length; /* Max 64 */
/** Private key passwd for enterprise mode */
const uint8_t *key_passwd;
/** Private key passwd length */
uint8_t key_passwd_length; /* Max 128 */
};

/** @brief Wi-Fi connect result codes. To be overlaid on top of \ref wifi_status
Expand Down Expand Up @@ -980,6 +996,14 @@ struct wifi_mgmt_ops {
* @return 0 if ok, < 0 if error
*/
int (*pmksa_flush)(const struct device *dev);
/** Set Wi-Fi enterprise mode CA/client Cert and key file
*
* @param dev Pointer to the device structure for the driver instance.
* @param file Pointer to the CA/client Cert and key file.
*
* @return 0 if ok, < 0 if error
*/
int (*enterprise_file)(const struct device *dev, void *file);
};

/** Wi-Fi management offload API */
Expand Down
116 changes: 116 additions & 0 deletions modules/hostap/src/supp_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ enum status_thread_state {

#define DISCONNECT_TIMEOUT_MS 5000

#ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
static struct wpa_supp_enterprise_file enterprise_file;
#endif

K_MUTEX_DEFINE(wpa_supplicant_mutex);

extern struct k_work_q *get_workq(void);
Expand Down Expand Up @@ -323,6 +327,59 @@ static inline enum wifi_security_type wpas_key_mgmt_to_zephyr(int key_mgmt, int
}
}

#ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
int supplicant_add_enterprise_file(const struct device *dev, void *file)
{
int ret = 0;

if (!file) {
ret = -1;
wpa_printf(MSG_ERROR, "enterprise file is NULL");
goto out;
}

memcpy((void *)&enterprise_file, (void *)file, sizeof(struct wpa_supp_enterprise_file));

out:
return ret;
}

static int wpas_config_process_blob(struct wpa_config *config, char *name, uint8_t *data,
uint32_t data_len)
{
struct wpa_config_blob *blob;

if (!data || !data_len) {
return -1;
}

blob = os_zalloc(sizeof(*blob));
if (blob == NULL) {
return -1;
}

blob->data = os_zalloc(data_len);
if (blob->data == NULL) {
os_free(blob);
return -1;
}

blob->name = os_strdup(name);

if (blob->name == NULL) {
wpa_config_free_blob(blob);
return -1;
}

os_memcpy(blob->data, data, data_len);
blob->len = data_len;

wpa_config_set_blob(config, blob);

return 0;
}
#endif

static int wpas_add_and_config_network(struct wpa_supplicant *wpa_s,
struct wifi_connect_req_params *params,
bool mode_ap)
Expand Down Expand Up @@ -445,6 +502,65 @@ static int wpas_add_and_config_network(struct wpa_supplicant *wpa_s,
goto out;
}
}
#ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
} else if (params->security == WIFI_SECURITY_TYPE_EAP_TLS) {
if (!wpa_cli_cmd_v("set_network %d key_mgmt WPA-EAP",
resp.network_id)) {
goto out;
}

if (!wpa_cli_cmd_v("set_network %d proto RSN",
resp.network_id)) {
goto out;
}

if (!wpa_cli_cmd_v("set_network %d eap TLS",
resp.network_id)) {
goto out;
}

if (!wpa_cli_cmd_v("set_network %d anonymous_identity \"%s\"",
resp.network_id, params->anon_id)) {
goto out;
}

if (wpas_config_process_blob(wpa_s->conf, "ca_cert",
enterprise_file.ca_cert, enterprise_file.ca_cert_len)) {
goto out;
}

if (!wpa_cli_cmd_v("set_network %d ca_cert \"blob://ca_cert\"",
resp.network_id)) {
goto out;
}

if (wpas_config_process_blob(wpa_s->conf, "client_cert",
enterprise_file.client_cert,
enterprise_file.client_cert_len)) {
goto out;
}

if (!wpa_cli_cmd_v("set_network %d client_cert \"blob://client_cert\"",
resp.network_id)) {
goto out;
}

if (wpas_config_process_blob(wpa_s->conf, "private_key",
enterprise_file.client_key,
enterprise_file.client_key_len)) {
goto out;
}

if (!wpa_cli_cmd_v("set_network %d private_key \"blob://private_key\"",
resp.network_id)) {
goto out;
}

if (!wpa_cli_cmd_v("set_network %d private_key_passwd \"%s\"",
resp.network_id, params->key_passwd)) {
goto out;
}
#endif
} else {
ret = -1;
wpa_printf(MSG_ERROR, "Unsupported security type: %d",
Expand Down
22 changes: 22 additions & 0 deletions modules/hostap/src/supp_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,17 @@
#define MAC_STR_LEN 18 /* for ':' or '-' separated MAC address string */
#define CHAN_NUM_LEN 6 /* for space-separated channel numbers string */

#ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
struct wpa_supp_enterprise_file {
uint8_t *ca_cert;
uint32_t ca_cert_len;
uint8_t *client_cert;
uint32_t client_cert_len;
uint8_t *client_key;
uint32_t client_key_len;
};
#endif

/**
* @brief Request a connection
*
Expand Down Expand Up @@ -127,6 +138,17 @@ int supplicant_reg_domain(const struct device *dev, struct wifi_reg_domain *reg_
*/
int supplicant_mode(const struct device *dev, struct wifi_mode_info *mode);

#ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
/** Set Wi-Fi enterprise mode CA/client Cert and key file
*
* @param dev Pointer to the device structure for the driver instance
* @param file Pointer to the CA/client Cert and key file.
*
* @return 0 if ok, < 0 if error
*/
int supplicant_add_enterprise_file(const struct device *dev, void *file);
#endif

/**
* @brief Set Wi-Fi packet filter for sniffing operation
*
Expand Down
1 change: 1 addition & 0 deletions modules/hostap/src/supp_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ static const struct wifi_mgmt_ops mgmt_ops = {
.ap_sta_disconnect = supplicant_ap_sta_disconnect,
#endif /* CONFIG_AP */
.pmksa_flush = supplicant_pmksa_flush,
.enterprise_file = supplicant_add_enterprise_file,
};

DEFINE_WIFI_NM_INSTANCE(wifi_supplicant, &mgmt_ops);
Expand Down
17 changes: 16 additions & 1 deletion subsys/net/l2/wifi/wifi_mgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const char *wifi_security_txt(enum wifi_security_type security)
return "WPA3-SAE";
case WIFI_SECURITY_TYPE_WAPI:
return "WAPI";
case WIFI_SECURITY_TYPE_EAP:
case WIFI_SECURITY_TYPE_EAP_TLS:
return "EAP";
case WIFI_SECURITY_TYPE_UNKNOWN:
default:
Expand Down Expand Up @@ -805,6 +805,21 @@ static int wifi_pmksa_flush(uint32_t mgmt_request, struct net_if *iface,

NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_PMKSA_FLUSH, wifi_pmksa_flush);

static int wifi_set_enterprise_file(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);

if (wifi_mgmt_api == NULL || wifi_mgmt_api->enterprise_file == NULL) {
return -ENOTSUP;
}

return wifi_mgmt_api->enterprise_file(dev, data);
}

NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_ENTERPRISE_FILE, wifi_set_enterprise_file);

#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)
Expand Down
31 changes: 27 additions & 4 deletions subsys/net/l2/wifi/wifi_shell.c
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,8 @@ static int __wifi_args_to_params(const struct shell *sh, size_t argc, char *argv
{"band", required_argument, 0, 'b'},
{"channel", required_argument, 0, 'c'},
{"timeout", required_argument, 0, 't'},
{"anon-id", required_argument, 0, 'a'},
{"key-passwd", required_argument, 0, 'K'},
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0}};
int opt_index = 0;
Expand All @@ -485,7 +487,7 @@ static int __wifi_args_to_params(const struct shell *sh, size_t argc, char *argv
params->security = WIFI_SECURITY_TYPE_NONE;
params->mfp = WIFI_MFP_OPTIONAL;

while ((opt = getopt_long(argc, argv, "s:p:k:w:b:c:m:t:h",
while ((opt = getopt_long(argc, argv, "s:p:k:w:b:c:m:t:a:K:h",
long_options, &opt_index)) != -1) {
state = getopt_state_get();
switch (opt) {
Expand Down Expand Up @@ -581,6 +583,24 @@ static int __wifi_args_to_params(const struct shell *sh, size_t argc, char *argv
}
}
break;
case 'a':
params->anon_id = optarg;
params->aid_length = strlen(params->anon_id);
if (params->aid_length > WIFI_IDENTITY_MAX_LEN) {
PR_WARNING("anon_id too long (max %d characters)\n",
WIFI_IDENTITY_MAX_LEN);
return -EINVAL;
}
break;
case 'K':
params->key_passwd = optarg;
params->key_passwd_length = strlen(params->key_passwd);
if (params->key_passwd_length > WIFI_PSWD_MAX_LEN) {
PR_WARNING("key_passwd too long (max %d characters)\n",
WIFI_PSWD_MAX_LEN);
return -EINVAL;
}
break;
case 'h':
return -ENOEXEC;
default:
Expand Down Expand Up @@ -1957,7 +1977,8 @@ SHELL_STATIC_SUBCMD_SET_CREATE(wifi_cmd_ap,
"-c --channel=<channel number>\n"
"-p --passphrase=<PSK> (valid only for secure SSIDs)\n"
"-k --key-mgmt=<Security type> (valid only for secure SSIDs)\n"
"0:None, 1:WPA2-PSK, 2:WPA2-PSK-256, 3:SAE, 4:WAPI, 5:EAP, 6:WEP, 7: WPA-PSK\n"
"0:None, 1:WPA2-PSK, 2:WPA2-PSK-256, 3:SAE, 4:WAPI, 5:WEP, 6: WPA-PSK\n"
"7: WPA-Auto-Personal, 8: EAP-TLS\n"
"-w --ieee-80211w=<MFP> (optional: needs security type to be specified)\n"
"0:Disable, 1:Optional, 2:Required\n"
"-b --band=<band> (2 -2.6GHz, 5 - 5Ghz, 6 - 6GHz)\n"
Expand Down Expand Up @@ -2021,12 +2042,14 @@ SHELL_STATIC_SUBCMD_SET_CREATE(wifi_commands,
"[-b, --band] 0: any band (2:2.4GHz, 5:5GHz, 6:6GHz]\n"
"[-p, --psk]: Passphrase (valid only for secure SSIDs)\n"
"[-k, --key-mgmt]: Key Management type (valid only for secure SSIDs)\n"
"0:None, 1:WPA2-PSK, 2:WPA2-PSK-256, 3:SAE, 4:WAPI, 5:EAP, 6:WEP,"
" 7: WPA-PSK, 8: WPA-Auto-Personal\n"
"0:None, 1:WPA2-PSK, 2:WPA2-PSK-256, 3:SAE, 4:WAPI, 5:WEP, 6: WPA-PSK\n"
"7: WPA-Auto-Personal, 8: EAP-TLS\n"
"[-w, --ieee-80211w]: MFP (optional: needs security type to be specified)\n"
": 0:Disable, 1:Optional, 2:Required.\n"
"[-m, --bssid]: MAC address of the AP (BSSID).\n"
"[-t, --timeout]: Timeout for the connection attempt (in seconds).\n"
"[-a, --anon-id]: Anonymous identity for enterprise mode.\n"
"[-K, --key-passwd]: Private key passwd for enterprise mode.\n"
"[-h, --help]: Print out the help for the connect command.\n",
cmd_wifi_connect,
2, 7),
Expand Down

0 comments on commit 5f9de8e

Please sign in to comment.