From 53587ec1836cc9532d33c872875e1bad422ab5ad Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 17 Jun 2010 18:35:18 -0700 Subject: [PATCH] WPS 2.0: Make WSC 2.0 support to be build option (CONFIG_WPS2) For now, the default build will only include WSC 1.0 support. CONFIG_WPS2=y can be used to add support for WSC 2.0. --- hostapd/Makefile | 4 +++ hostapd/README-WPS | 1 + hostapd/defconfig | 2 ++ src/wps/wps.c | 11 ++++++- src/wps/wps_attr_build.c | 4 +++ src/wps/wps_attr_parse.c | 4 +++ src/wps/wps_common.c | 4 +++ src/wps/wps_defs.h | 8 +++++ src/wps/wps_enrollee.c | 6 ++++ src/wps/wps_er.c | 2 ++ src/wps/wps_registrar.c | 50 +++++++++++++++++++++--------- wpa_supplicant/Makefile | 4 +++ wpa_supplicant/README-WPS | 1 + wpa_supplicant/ctrl_iface.c | 2 ++ wpa_supplicant/defconfig | 2 ++ wpa_supplicant/wpa_supplicant.conf | 3 ++ 16 files changed, 93 insertions(+), 15 deletions(-) diff --git a/hostapd/Makefile b/hostapd/Makefile index 2361c0e8f..a91aeaa58 100644 --- a/hostapd/Makefile +++ b/hostapd/Makefile @@ -289,6 +289,10 @@ NEED_AES_UNWRAP=y endif ifdef CONFIG_WPS +ifdef CONFIG_WPS2 +CFLAGS += -DCONFIG_WPS2 +endif + CFLAGS += -DCONFIG_WPS -DEAP_SERVER_WSC OBJS += ../src/utils/uuid.o OBJS += ../src/ap/wps_hostapd.o diff --git a/hostapd/README-WPS b/hostapd/README-WPS index 3bfde616a..64561d025 100644 --- a/hostapd/README-WPS +++ b/hostapd/README-WPS @@ -63,6 +63,7 @@ includes WPS support and uses madwifi driver interface: CONFIG_DRIVER_MADWIFI=y CFLAGS += -I/usr/src/madwifi-0.9.3 CONFIG_WPS=y +CONFIG_WPS2=y CONFIG_WPS_UPNP=y diff --git a/hostapd/defconfig b/hostapd/defconfig index 1d28c022f..3ecb7e30d 100644 --- a/hostapd/defconfig +++ b/hostapd/defconfig @@ -107,6 +107,8 @@ CONFIG_EAP_TTLS=y # Wi-Fi Protected Setup (WPS) #CONFIG_WPS=y +# Enable WSC 2.0 support +#CONFIG_WPS2=y # Enable UPnP support for external WPS Registrars #CONFIG_WPS_UPNP=y diff --git a/src/wps/wps.c b/src/wps/wps.c index 48cc2d84e..1361b73cc 100644 --- a/src/wps/wps.c +++ b/src/wps/wps.c @@ -437,12 +437,14 @@ struct wpabuf * wps_build_probe_req_ie(int pbc, struct wps_device_data *dev, if (pbc) { methods = WPS_CONFIG_PUSHBUTTON; +#ifdef CONFIG_WPS2 /* * TODO: At least in theory, should figure out whether this * Probe Request was triggered with physical or virtual * pushbutton. */ methods |= WPS_CONFIG_VIRT_PUSHBUTTON; +#endif /* CONFIG_WPS2 */ } else { /* * TODO: At least in theory, should figure out whether this @@ -450,7 +452,9 @@ struct wpabuf * wps_build_probe_req_ie(int pbc, struct wps_device_data *dev, * display. */ methods = WPS_CONFIG_LABEL | WPS_CONFIG_DISPLAY | +#ifdef CONFIG_WPS2 WPS_CONFIG_VIRT_DISPLAY | +#endif /* CONFIG_WPS2 */ WPS_CONFIG_KEYPAD; #ifdef CONFIG_WPS_UFD methods |= WPS_CONFIG_USBA; @@ -470,13 +474,18 @@ struct wpabuf * wps_build_probe_req_ie(int pbc, struct wps_device_data *dev, wps_build_config_error(ie, WPS_CFG_NO_ERROR) || wps_build_dev_password_id(ie, pbc ? DEV_PW_PUSHBUTTON : DEV_PW_DEFAULT) || +#ifdef CONFIG_WPS2 wps_build_version2(ie) || wps_build_manufacturer(dev, ie) || wps_build_model_name(dev, ie) || wps_build_model_number(dev, ie) || wps_build_dev_name(dev, ie) || (req_type == WPS_REQ_ENROLLEE && - wps_build_req_to_enroll(ie))) { + wps_build_req_to_enroll(ie)) +#else /* CONFIG_WPS2 */ + 0 +#endif /* CONFIG_WPS2 */ + ) { wpabuf_free(ie); return NULL; } diff --git a/src/wps/wps_attr_build.c b/src/wps/wps_attr_build.c index 3ec8204cc..28801417a 100644 --- a/src/wps/wps_attr_build.c +++ b/src/wps/wps_attr_build.c @@ -174,6 +174,7 @@ int wps_build_version(struct wpabuf *msg) int wps_build_version2(struct wpabuf *msg) { +#ifdef CONFIG_WPS2 wpa_printf(MSG_DEBUG, "WPS: * Version2 (0x%x)", WPS_VERSION); wpabuf_put_be16(msg, ATTR_VERSION2); wpabuf_put_be16(msg, 1); @@ -185,6 +186,7 @@ int wps_build_version2(struct wpabuf *msg) wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, 42); #endif /* CONFIG_WPS_EXTENSIBILITY_TESTING */ +#endif /* CONFIG_WPS2 */ return 0; } @@ -349,10 +351,12 @@ int wps_build_oob_dev_password(struct wpabuf *msg, struct wps_context *wps) int wps_build_req_to_enroll(struct wpabuf *msg) { +#ifdef CONFIG_WPS2 wpa_printf(MSG_DEBUG, "WPS: * Request to Enroll (1)"); wpabuf_put_be16(msg, ATTR_REQUEST_TO_ENROLL); wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, 1); +#endif /* CONFIG_WPS2 */ return 0; } diff --git a/src/wps/wps_attr_parse.c b/src/wps/wps_attr_parse.c index ffce49591..70e3c60d4 100644 --- a/src/wps/wps_attr_parse.c +++ b/src/wps/wps_attr_parse.c @@ -34,6 +34,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, } attr->version = pos; break; +#ifdef CONFIG_WPS2 case ATTR_VERSION2: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid Version2 length " @@ -42,6 +43,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, } attr->version2 = pos; break; +#endif /* CONFIG_WPS2 */ case ATTR_MSG_TYPE: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type " @@ -409,6 +411,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, } attr->ap_setup_locked = pos; break; +#ifdef CONFIG_WPS2 case ATTR_SETTINGS_DELAY_TIME: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid Settings Delay " @@ -452,6 +455,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, attr->req_dev_type[attr->num_req_dev_type] = pos; attr->num_req_dev_type++; break; +#endif /* CONFIG_WPS2 */ default: wpa_printf(MSG_DEBUG, "WPS: Unsupported attribute type 0x%x " "len=%u", type, len); diff --git a/src/wps/wps_common.c b/src/wps/wps_common.c index a6a959433..001f7f290 100644 --- a/src/wps/wps_common.c +++ b/src/wps/wps_common.c @@ -609,7 +609,9 @@ u16 wps_config_methods_str2bin(const char *str) if (str == NULL) { /* Default to enabling methods based on build configuration */ methods |= WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD; +#ifdef CONFIG_WPS2 methods |= WPS_CONFIG_VIRT_DISPLAY; +#endif /* CONFIG_WPS2 */ #ifdef CONFIG_WPS_UFD methods |= WPS_CONFIG_USBA; #endif /* CONFIG_WPS_UFD */ @@ -635,6 +637,7 @@ u16 wps_config_methods_str2bin(const char *str) methods |= WPS_CONFIG_PUSHBUTTON; if (os_strstr(str, "keypad")) methods |= WPS_CONFIG_KEYPAD; +#ifdef CONFIG_WPS2 if (os_strstr(str, "virtual_display")) methods |= WPS_CONFIG_VIRT_DISPLAY; if (os_strstr(str, "physical_display")) @@ -643,6 +646,7 @@ u16 wps_config_methods_str2bin(const char *str) methods |= WPS_CONFIG_VIRT_PUSHBUTTON; if (os_strstr(str, "physical_push_button")) methods |= WPS_CONFIG_PHY_PUSHBUTTON; +#endif /* CONFIG_WPS2 */ } return methods; diff --git a/src/wps/wps_defs.h b/src/wps/wps_defs.h index 13716de9d..1343a43e2 100644 --- a/src/wps/wps_defs.h +++ b/src/wps/wps_defs.h @@ -15,11 +15,15 @@ #ifndef WPS_DEFS_H #define WPS_DEFS_H +#ifdef CONFIG_WPS2 #ifdef CONFIG_WPS_EXTENSIBILITY_TESTING #define WPS_VERSION 0x57 #else /* CONFIG_WPS_EXTENSIBILITY_TESTING */ #define WPS_VERSION 0x20 #endif /* CONFIG_WPS_EXTENSIBILITY_TESTING */ +#else /* CONFIG_WPS2 */ +#define WPS_VERSION 0x10 +#endif /* CONFIG_WPS2 */ /* Diffie-Hellman 1536-bit MODP Group; RFC 3526, Group 5 */ #define WPS_DH_GROUP 5 @@ -129,12 +133,14 @@ enum wps_attribute { ATTR_802_1X_ENABLED = 0x1062, ATTR_APPSESSIONKEY = 0x1063, ATTR_WEPTRANSMITKEY = 0x1064, +#ifdef CONFIG_WPS2 ATTR_SETTINGS_DELAY_TIME = 0x1065, ATTR_NETWORK_KEY_SHAREABLE = 0x1066, ATTR_VERSION2 = 0x1067, ATTR_REQUEST_TO_ENROLL = 0x1068, ATTR_AUTHORIZED_MACS = 0x1069, ATTR_REQUESTED_DEV_TYPE = 0x106a, +#endif /* CONFIG_WPS2 */ ATTR_EXTENSIBILITY_TEST = 0x10fa /* _NOT_ defined in the spec */ }; @@ -222,10 +228,12 @@ enum wps_config_error { #define WPS_CONFIG_NFC_INTERFACE 0x0040 #define WPS_CONFIG_PUSHBUTTON 0x0080 #define WPS_CONFIG_KEYPAD 0x0100 +#ifdef CONFIG_WPS2 #define WPS_CONFIG_VIRT_PUSHBUTTON 0x0280 #define WPS_CONFIG_PHY_PUSHBUTTON 0x0480 #define WPS_CONFIG_VIRT_DISPLAY 0x2008 #define WPS_CONFIG_PHY_DISPLAY 0x4008 +#endif /* CONFIG_WPS2 */ /* Connection Type Flags */ #define WPS_CONN_ESS 0x01 diff --git a/src/wps/wps_enrollee.c b/src/wps/wps_enrollee.c index 8f915b2d9..6e2b51137 100644 --- a/src/wps/wps_enrollee.c +++ b/src/wps/wps_enrollee.c @@ -698,6 +698,7 @@ static int wps_process_cred_e(struct wps_data *wps, const u8 *cred, #endif /* CONFIG_WPS_STRICT */ } +#ifdef CONFIG_WPS2 if (!(wps->cred.encr_type & (WPS_ENCR_NONE | WPS_ENCR_TKIP | WPS_ENCR_AES))) { if (wps->cred.encr_type & WPS_ENCR_WEP) { @@ -710,6 +711,7 @@ static int wps_process_cred_e(struct wps_data *wps, const u8 *cred, "invalid encr_type 0x%x", wps->cred.encr_type); return -1; } +#endif /* CONFIG_WPS2 */ if (wps->wps->cred_cb) { wps->cred.cred_attr = cred - 4; @@ -796,6 +798,7 @@ static int wps_process_ap_settings_e(struct wps_data *wps, #endif /* CONFIG_WPS_STRICT */ } +#ifdef CONFIG_WPS2 if (!(cred.encr_type & (WPS_ENCR_NONE | WPS_ENCR_TKIP | WPS_ENCR_AES))) { if (cred.encr_type & WPS_ENCR_WEP) { @@ -808,6 +811,7 @@ static int wps_process_ap_settings_e(struct wps_data *wps, "invalid encr_type 0x%x", cred.encr_type); return -1; } +#endif /* CONFIG_WPS2 */ #ifdef CONFIG_WPS_STRICT if (wps2) { @@ -822,6 +826,7 @@ static int wps_process_ap_settings_e(struct wps_data *wps, } #endif /* CONFIG_WPS_STRICT */ +#ifdef CONFIG_WPS2 if ((cred.encr_type & (WPS_ENCR_TKIP | WPS_ENCR_AES)) == WPS_ENCR_TKIP) { wpa_printf(MSG_DEBUG, "WPS: Upgrade encr_type TKIP -> " @@ -835,6 +840,7 @@ static int wps_process_ap_settings_e(struct wps_data *wps, "WPAPSK+WPA2PSK"); cred.auth_type |= WPS_AUTH_WPA2PSK; } +#endif /* CONFIG_WPS2 */ if (wps->wps->cred_cb) { cred.cred_attr = wpabuf_head(attrs); diff --git a/src/wps/wps_er.c b/src/wps/wps_er.c index 9f5074af4..51306cb0f 100644 --- a/src/wps/wps_er.c +++ b/src/wps/wps_er.c @@ -1351,9 +1351,11 @@ static int wps_er_build_sel_reg_config_methods(struct wpabuf *msg, static int wps_er_build_uuid_r(struct wpabuf *msg, const u8 *uuid_r) { +#ifdef CONFIG_WPS2 wpabuf_put_be16(msg, ATTR_UUID_R); wpabuf_put_be16(msg, WPS_UUID_LEN); wpabuf_put_data(msg, uuid_r, WPS_UUID_LEN); +#endif /* CONFIG_WPS2 */ return 0; } diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c index 3fc541ff0..96d0bfcf8 100644 --- a/src/wps/wps_registrar.c +++ b/src/wps/wps_registrar.c @@ -422,15 +422,20 @@ static int wps_build_sel_reg_config_methods(struct wps_registrar *reg, u16 methods; if (!reg->sel_reg_union) return 0; - methods = reg->wps->config_methods & - ~(WPS_CONFIG_PUSHBUTTON | WPS_CONFIG_VIRT_PUSHBUTTON | - WPS_CONFIG_PHY_PUSHBUTTON); + methods = reg->wps->config_methods; + methods &= ~WPS_CONFIG_PUSHBUTTON; +#ifdef CONFIG_WPS2 + methods &= ~(WPS_CONFIG_VIRT_PUSHBUTTON | + WPS_CONFIG_PHY_PUSHBUTTON); +#endif /* CONFIG_WPS2 */ if (reg->pbc) { methods |= WPS_CONFIG_PUSHBUTTON; +#ifdef CONFIG_WPS2 if (reg->wps->config_methods & WPS_CONFIG_VIRT_PUSHBUTTON) methods |= WPS_CONFIG_VIRT_PUSHBUTTON; if (reg->wps->config_methods & WPS_CONFIG_PHY_PUSHBUTTON) methods |= WPS_CONFIG_PHY_PUSHBUTTON; +#endif /* CONFIG_WPS2 */ } if (reg->sel_reg_config_methods_override >= 0) methods = reg->sel_reg_config_methods_override; @@ -451,9 +456,11 @@ static int wps_build_probe_config_methods(struct wps_registrar *reg, * These are the methods that the AP supports as an Enrollee for adding * external Registrars. */ - methods = reg->wps->config_methods & - ~(WPS_CONFIG_PUSHBUTTON | WPS_CONFIG_VIRT_PUSHBUTTON | - WPS_CONFIG_PHY_PUSHBUTTON); + methods = reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON; +#ifdef CONFIG_WPS2 + methods &= ~(WPS_CONFIG_VIRT_PUSHBUTTON | + WPS_CONFIG_PHY_PUSHBUTTON); +#endif /* CONFIG_WPS2 */ wpa_printf(MSG_DEBUG, "WPS: * Config Methods (%x)", methods); wpabuf_put_be16(msg, ATTR_CONFIG_METHODS); wpabuf_put_be16(msg, 2); @@ -466,15 +473,19 @@ static int wps_build_config_methods_r(struct wps_registrar *reg, struct wpabuf *msg) { u16 methods; - methods = reg->wps->config_methods & - ~(WPS_CONFIG_PUSHBUTTON | WPS_CONFIG_VIRT_PUSHBUTTON | - WPS_CONFIG_PHY_PUSHBUTTON); + methods = reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON; +#ifdef CONFIG_WPS2 + methods &= ~(WPS_CONFIG_VIRT_PUSHBUTTON | + WPS_CONFIG_PHY_PUSHBUTTON); +#endif /* CONFIG_WPS2 */ if (reg->pbc) { methods |= WPS_CONFIG_PUSHBUTTON; +#ifdef CONFIG_WPS2 if (reg->wps->config_methods & WPS_CONFIG_VIRT_PUSHBUTTON) methods |= WPS_CONFIG_VIRT_PUSHBUTTON; if (reg->wps->config_methods & WPS_CONFIG_PHY_PUSHBUTTON) methods |= WPS_CONFIG_PHY_PUSHBUTTON; +#endif /* CONFIG_WPS2 */ } return wps_build_config_methods(msg, methods); } @@ -482,6 +493,7 @@ static int wps_build_config_methods_r(struct wps_registrar *reg, int wps_build_authorized_macs(struct wps_registrar *reg, struct wpabuf *msg) { +#ifdef CONFIG_WPS2 int count = 0; while (count < WPS_MAX_AUTHORIZED_MACS) { @@ -497,6 +509,7 @@ int wps_build_authorized_macs(struct wps_registrar *reg, struct wpabuf *msg) wpabuf_put_be16(msg, ATTR_AUTHORIZED_MACS); wpabuf_put_be16(msg, count * ETH_ALEN); wpabuf_put_data(msg, reg->authorized_macs_union, count * ETH_ALEN); +#endif /* CONFIG_WPS2 */ return 0; } @@ -938,17 +951,21 @@ static void wps_cb_set_sel_reg(struct wps_registrar *reg) return; if (reg->selected_registrar) { - methods = reg->wps->config_methods & - ~(WPS_CONFIG_PUSHBUTTON | WPS_CONFIG_VIRT_PUSHBUTTON | - WPS_CONFIG_PHY_PUSHBUTTON); + methods = reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON; +#ifdef CONFIG_WPS2 + methods &= ~(WPS_CONFIG_VIRT_PUSHBUTTON | + WPS_CONFIG_PHY_PUSHBUTTON); +#endif /* CONFIG_WPS2 */ if (reg->pbc) { methods |= WPS_CONFIG_PUSHBUTTON; +#ifdef CONFIG_WPS2 if (reg->wps->config_methods & WPS_CONFIG_VIRT_PUSHBUTTON) methods |= WPS_CONFIG_VIRT_PUSHBUTTON; if (reg->wps->config_methods & WPS_CONFIG_PHY_PUSHBUTTON) methods |= WPS_CONFIG_PHY_PUSHBUTTON; +#endif /* CONFIG_WPS2 */ } } @@ -2963,14 +2980,18 @@ void wps_registrar_selected_registrar_changed(struct wps_registrar *reg) WPS_MAX_AUTHORIZED_MACS * ETH_ALEN); if (reg->selected_registrar) { reg->sel_reg_config_methods_override = - reg->wps->config_methods & - ~(WPS_CONFIG_PUSHBUTTON | WPS_CONFIG_VIRT_PUSHBUTTON | + reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON; +#ifdef CONFIG_WPS2 + reg->sel_reg_config_methods_override &= + ~(WPS_CONFIG_VIRT_PUSHBUTTON | WPS_CONFIG_PHY_PUSHBUTTON); +#endif /* CONFIG_WPS2 */ if (reg->pbc) { reg->sel_reg_dev_password_id_override = DEV_PW_PUSHBUTTON; reg->sel_reg_config_methods_override |= WPS_CONFIG_PUSHBUTTON; +#ifdef CONFIG_WPS2 if (reg->wps->config_methods & WPS_CONFIG_VIRT_PUSHBUTTON) reg->sel_reg_config_methods_override |= @@ -2979,6 +3000,7 @@ void wps_registrar_selected_registrar_changed(struct wps_registrar *reg) WPS_CONFIG_PHY_PUSHBUTTON) reg->sel_reg_config_methods_override |= WPS_CONFIG_PHY_PUSHBUTTON; +#endif /* CONFIG_WPS2 */ } wpa_printf(MSG_DEBUG, "WPS: Internal Registrar selected " "(pbc=%d)", reg->pbc); diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index e6a51c783..4bc00e272 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -455,6 +455,10 @@ NEED_AES_OMAC1=y endif ifdef CONFIG_WPS +ifdef CONFIG_WPS2 +CFLAGS += -DCONFIG_WPS2 +endif + # EAP-WSC CFLAGS += -DCONFIG_WPS -DEAP_WSC OBJS += wps_supplicant.o diff --git a/wpa_supplicant/README-WPS b/wpa_supplicant/README-WPS index 9b6f9c554..7c2883688 100644 --- a/wpa_supplicant/README-WPS +++ b/wpa_supplicant/README-WPS @@ -62,6 +62,7 @@ configuration that includes WPS support and Linux wireless extensions CONFIG_DRIVER_WEXT=y CONFIG_WPS=y +CONFIG_WPS2=y WPS needs the Universally Unique IDentifier (UUID; see RFC 4122) for diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 4a2412fcc..9c849cbf5 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -836,8 +836,10 @@ static char * wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant *wpa_s, return pos; if (wps_is_selected_pbc_registrar(wps_ie)) txt = "[WPS-PBC]"; +#ifdef CONFIG_WPS2 else if (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 0)) txt = "[WPS-AUTH]"; +#endif /* CONFIG_WPS2 */ else if (wps_is_selected_pin_registrar(wps_ie)) txt = "[WPS-PIN]"; else diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig index 3e3808d2c..9f94e0afe 100644 --- a/wpa_supplicant/defconfig +++ b/wpa_supplicant/defconfig @@ -194,6 +194,8 @@ CONFIG_EAP_LEAP=y # Wi-Fi Protected Setup (WPS) #CONFIG_WPS=y +# Enable WSC 2.0 support +#CONFIG_WPS2=y # EAP-IKEv2 #CONFIG_EAP_IKEV2=y diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index ea00e988b..b01574464 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -201,6 +201,9 @@ fast_reauth=1 # Available methods: usba ethernet label display ext_nfc_token int_nfc_token # nfc_interface push_button keypad virtual_display physical_display # virtual_push_button physical_push_button +# For WSC 1.0: +#config_methods=label display push_button keypad +# For WSC 2.0: #config_methods=label virtual_display virtual_push_button keypad # Credential processing