From 9173b16fd194269878a6a29f4452be22d6cb53c2 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 3 Aug 2012 21:36:38 +0300 Subject: [PATCH] EXT PW: Add support for psk parameter from external storage This allows wpa_supplicant configuration file to be created without the PSK/passphrase value included in the file when a backend for external password storage is available. Following example can be used for developer testing: ext_password_backend=test:psk1=12345678 network={ ssid="test-psk" key_mgmt=WPA-PSK psk=ext:psk1 } Signed-hostap: Jouni Malinen --- wpa_supplicant/config.c | 27 ++++++++++++++ wpa_supplicant/wpa_supplicant.c | 60 +++++++++++++++++++++++++++++- wpa_supplicant/wpa_supplicant.conf | 3 +- 3 files changed, 88 insertions(+), 2 deletions(-) diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 9d7f38ed1..70c28fe85 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -324,6 +324,21 @@ static int wpa_config_parse_psk(const struct parse_data *data, struct wpa_ssid *ssid, int line, const char *value) { +#ifdef CONFIG_EXT_PASSWORD + if (os_strncmp(value, "ext:", 4) == 0) { + os_free(ssid->passphrase); + ssid->passphrase = NULL; + ssid->psk_set = 0; + os_free(ssid->ext_psk); + ssid->ext_psk = os_strdup(value + 4); + if (ssid->ext_psk == NULL) + return -1; + wpa_printf(MSG_DEBUG, "PSK: External password '%s'", + ssid->ext_psk); + return 0; + } +#endif /* CONFIG_EXT_PASSWORD */ + if (*value == '"') { #ifndef CONFIG_NO_PBKDF2 const char *pos; @@ -381,6 +396,17 @@ static int wpa_config_parse_psk(const struct parse_data *data, static char * wpa_config_write_psk(const struct parse_data *data, struct wpa_ssid *ssid) { +#ifdef CONFIG_EXT_PASSWORD + if (ssid->ext_psk) { + size_t len = 4 + os_strlen(ssid->ext_psk) + 1; + char *buf = os_malloc(len); + if (buf == NULL) + return NULL; + os_snprintf(buf, len, "ext:%s", ssid->ext_psk); + return buf; + } +#endif /* CONFIG_EXT_PASSWORD */ + if (ssid->passphrase) return wpa_config_write_string_ascii( (const u8 *) ssid->passphrase, @@ -1771,6 +1797,7 @@ void wpa_config_free_ssid(struct wpa_ssid *ssid) { os_free(ssid->ssid); os_free(ssid->passphrase); + os_free(ssid->ext_psk); #ifdef IEEE8021X_EAPOL eap_peer_config_free(&ssid->eap); #endif /* IEEE8021X_EAPOL */ diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 924719547..61fbec99c 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1104,6 +1104,63 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN); } #endif /* CONFIG_NO_PBKDF2 */ +#ifdef CONFIG_EXT_PASSWORD + if (ssid->ext_psk) { + struct wpabuf *pw = ext_password_get(wpa_s->ext_pw, + ssid->ext_psk); + char pw_str[64 + 1]; + u8 psk[PMK_LEN]; + + if (pw == NULL) { + wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK " + "found from external storage"); + return -1; + } + + if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) { + wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected " + "PSK length %d in external storage", + (int) wpabuf_len(pw)); + ext_password_free(pw); + return -1; + } + + os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw)); + pw_str[wpabuf_len(pw)] = '\0'; + +#ifndef CONFIG_NO_PBKDF2 + if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss) + { + pbkdf2_sha1(pw_str, (char *) bss->ssid, + bss->ssid_len, 4096, psk, PMK_LEN); + os_memset(pw_str, 0, sizeof(pw_str)); + wpa_hexdump_key(MSG_MSGDUMP, "PSK (from " + "external passphrase)", + psk, PMK_LEN); + wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN); + } else +#endif /* CONFIG_NO_PBKDF2 */ + if (wpabuf_len(pw) == 2 * PMK_LEN) { + if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) { + wpa_msg(wpa_s, MSG_INFO, "EXT PW: " + "Invalid PSK hex string"); + os_memset(pw_str, 0, sizeof(pw_str)); + ext_password_free(pw); + return -1; + } + wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN); + } else { + wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable " + "PSK available"); + os_memset(pw_str, 0, sizeof(pw_str)); + ext_password_free(pw); + return -1; + } + + os_memset(pw_str, 0, sizeof(pw_str)); + ext_password_free(pw); + } +#endif /* CONFIG_EXT_PASSWORD */ } else wpa_sm_set_pmk_from_pmksa(wpa_s->wpa); @@ -3430,7 +3487,8 @@ int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) return 1; /* invalid WEP key */ } - if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set) + if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set && + !ssid->ext_psk) return 1; return 0; diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index 05a2d0bc2..9f1cd00fb 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -508,7 +508,8 @@ fast_reauth=1 # The key used in WPA-PSK mode can be entered either as 64 hex-digits, i.e., # 32 bytes or as an ASCII passphrase (in which case, the real PSK will be # generated using the passphrase and SSID). ASCII passphrase must be between -# 8 and 63 characters (inclusive). +# 8 and 63 characters (inclusive). ext: format can +# be used to indicate that the PSK/passphrase is stored in external storage. # This field is not needed, if WPA-EAP is used. # Note: Separate tool, wpa_passphrase, can be used to generate 256-bit keys # from ASCII passphrase. This process uses lot of CPU and wpa_supplicant