diff --git a/include/zephyr/net/wifi.h b/include/zephyr/net/wifi.h index 6f8bfc0cf9d7c0e..ed83b112421f5db 100644 --- a/include/zephyr/net/wifi.h +++ b/include/zephyr/net/wifi.h @@ -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, @@ -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 diff --git a/include/zephyr/net/wifi_mgmt.h b/include/zephyr/net/wifi_mgmt.h index bcdf4dc25a5672e..98b0a8eefe1c724 100644 --- a/include/zephyr/net/wifi_mgmt.h +++ b/include/zephyr/net/wifi_mgmt.h @@ -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 */ @@ -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 */ @@ -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 @@ -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 */ diff --git a/modules/hostap/src/supp_api.c b/modules/hostap/src/supp_api.c index 9d6dafaf41c2aaa..15e9af4ce7ba039 100644 --- a/modules/hostap/src/supp_api.c +++ b/modules/hostap/src/supp_api.c @@ -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); @@ -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) @@ -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", diff --git a/modules/hostap/src/supp_api.h b/modules/hostap/src/supp_api.h index 566a73d7bd8b0e0..37824bdf24b5648 100644 --- a/modules/hostap/src/supp_api.h +++ b/modules/hostap/src/supp_api.h @@ -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 * @@ -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 * diff --git a/modules/hostap/src/supp_main.c b/modules/hostap/src/supp_main.c index 9abd41131a7686f..10faf03da327a37 100644 --- a/modules/hostap/src/supp_main.c +++ b/modules/hostap/src/supp_main.c @@ -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); diff --git a/subsys/net/l2/wifi/wifi_mgmt.c b/subsys/net/l2/wifi/wifi_mgmt.c index cabe8a7091cea15..d1d30dfe4cc9f39 100644 --- a/subsys/net/l2/wifi/wifi_mgmt.c +++ b/subsys/net/l2/wifi/wifi_mgmt.c @@ -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: @@ -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) diff --git a/subsys/net/l2/wifi/wifi_shell.c b/subsys/net/l2/wifi/wifi_shell.c index ffc730a9d612aa5..56d2598f380491f 100644 --- a/subsys/net/l2/wifi/wifi_shell.c +++ b/subsys/net/l2/wifi/wifi_shell.c @@ -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; @@ -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) { @@ -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: @@ -1957,7 +1977,8 @@ SHELL_STATIC_SUBCMD_SET_CREATE(wifi_cmd_ap, "-c --channel=\n" "-p --passphrase= (valid only for secure SSIDs)\n" "-k --key-mgmt= (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= (optional: needs security type to be specified)\n" "0:Disable, 1:Optional, 2:Required\n" "-b --band= (2 -2.6GHz, 5 - 5Ghz, 6 - 6GHz)\n" @@ -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),