]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Clear wpa_supplicant configuration keys explicitly
authorJouni Malinen <j@w1.fi>
Sun, 29 Jun 2014 22:32:07 +0000 (01:32 +0300)
committerJouni Malinen <j@w1.fi>
Wed, 2 Jul 2014 09:38:48 +0000 (12:38 +0300)
Use an explicit memset call to clear any wpa_supplicant configuration
parameter that contains private information like keys or identity. This
brings in an additional layer of protection by reducing the length of
time this type of private data is kept in memory.

Signed-off-by: Jouni Malinen <j@w1.fi>
src/eap_peer/eap_config.h
src/utils/common.c
src/utils/common.h
src/utils/ext_password_test.c
wpa_supplicant/config.c
wpa_supplicant/wpa_supplicant.c

index daa1d3288ad11e14a1d1879c7111606147e326b0..2591e113a5c6b549a98acf88bf8fa838eed36e31 100644 (file)
@@ -157,7 +157,7 @@ struct eap_peer_config {
         *
         * If left out, this will be asked through control interface.
         */
-       u8 *private_key_passwd;
+       char *private_key_passwd;
 
        /**
         * dh_file - File path to DH/DSA parameters file (in PEM format)
@@ -289,7 +289,7 @@ struct eap_peer_config {
         * This field is like private_key_passwd, but used for phase 2 (inside
         * EAP-TTLS/PEAP/FAST tunnel) authentication.
         */
-       u8 *private_key2_passwd;
+       char *private_key2_passwd;
 
        /**
         * dh_file2 - File path to DH/DSA parameters file (in PEM format)
index 7dc4797d1bf6ce247552a3313959e3f4d45f6996..5b017e57ac88453a5f5081e718dc1d4cbf0e7389 100644 (file)
@@ -827,3 +827,22 @@ void int_array_add_unique(int **res, int a)
 
        *res = n;
 }
+
+
+void str_clear_free(char *str)
+{
+       if (str) {
+               size_t len = os_strlen(str);
+               os_memset(str, 0, len);
+               os_free(str);
+       }
+}
+
+
+void bin_clear_free(void *bin, size_t len)
+{
+       if (bin) {
+               os_memset(bin, 0, len);
+               os_free(bin);
+       }
+}
index a85cc159df63573b47fb08ef1c75c1b8f9ae061b..2bc8fe1432fe3f43efc31e430f1c3386c37c572e 100644 (file)
@@ -535,6 +535,10 @@ void int_array_add_unique(int **res, int a);
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
 
 
+void str_clear_free(char *str);
+void bin_clear_free(void *bin, size_t len);
+
+
 /*
  * gcc 4.4 ends up generating strict-aliasing warnings about some very common
  * networking socket uses that do not really result in a real problem and
index 3801bb85449fe624a8cc238d7e445bab761967da..b3a4552d1c2c4e0a443eb89d567e3a741f09ae09 100644 (file)
@@ -36,7 +36,7 @@ static void ext_password_test_deinit(void *ctx)
 {
        struct ext_password_test_data *data = ctx;
 
-       os_free(data->params);
+       str_clear_free(data->params);
        os_free(data);
 }
 
index 36558c908fb984058914f0915e259d215abc8d47..e666c9b362107e3f94fa2181685c6005485b4654 100644 (file)
@@ -286,7 +286,7 @@ static int wpa_config_parse_psk(const struct parse_data *data,
 {
 #ifdef CONFIG_EXT_PASSWORD
        if (os_strncmp(value, "ext:", 4) == 0) {
-               os_free(ssid->passphrase);
+               str_clear_free(ssid->passphrase);
                ssid->passphrase = NULL;
                ssid->psk_set = 0;
                os_free(ssid->ext_psk);
@@ -322,7 +322,7 @@ static int wpa_config_parse_psk(const struct parse_data *data,
                    os_memcmp(ssid->passphrase, value, len) == 0)
                        return 0;
                ssid->psk_set = 0;
-               os_free(ssid->passphrase);
+               str_clear_free(ssid->passphrase);
                ssid->passphrase = dup_binstr(value, len);
                if (ssid->passphrase == NULL)
                        return -1;
@@ -341,7 +341,7 @@ static int wpa_config_parse_psk(const struct parse_data *data,
                return -1;
        }
 
-       os_free(ssid->passphrase);
+       str_clear_free(ssid->passphrase);
        ssid->passphrase = NULL;
 
        ssid->psk_set = 1;
@@ -1130,7 +1130,7 @@ static int wpa_config_parse_password(const struct parse_data *data,
 
        if (os_strcmp(value, "NULL") == 0) {
                wpa_printf(MSG_DEBUG, "Unset configuration string 'password'");
-               os_free(ssid->eap.password);
+               bin_clear_free(ssid->eap.password, ssid->eap.password_len);
                ssid->eap.password = NULL;
                ssid->eap.password_len = 0;
                return 0;
@@ -1141,7 +1141,7 @@ static int wpa_config_parse_password(const struct parse_data *data,
                char *name = os_strdup(value + 4);
                if (name == NULL)
                        return -1;
-               os_free(ssid->eap.password);
+               bin_clear_free(ssid->eap.password, ssid->eap.password_len);
                ssid->eap.password = (u8 *) name;
                ssid->eap.password_len = os_strlen(name);
                ssid->eap.flags &= ~EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
@@ -1163,7 +1163,7 @@ static int wpa_config_parse_password(const struct parse_data *data,
                wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name,
                                      (u8 *) tmp, res_len);
 
-               os_free(ssid->eap.password);
+               bin_clear_free(ssid->eap.password, ssid->eap.password_len);
                ssid->eap.password = (u8 *) tmp;
                ssid->eap.password_len = res_len;
                ssid->eap.flags &= ~EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
@@ -1192,7 +1192,7 @@ static int wpa_config_parse_password(const struct parse_data *data,
 
        wpa_hexdump_key(MSG_MSGDUMP, data->name, hash, 16);
 
-       os_free(ssid->eap.password);
+       bin_clear_free(ssid->eap.password, ssid->eap.password_len);
        ssid->eap.password = hash;
        ssid->eap.password_len = 16;
        ssid->eap.flags |= EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
@@ -1262,7 +1262,7 @@ static int wpa_config_parse_wep_key(u8 *key, size_t *len, int line,
                           line, (unsigned int) *len);
        }
        os_memcpy(key, buf, *len);
-       os_free(buf);
+       str_clear_free(buf);
        res = os_snprintf(title, sizeof(title), "wep_key%d", idx);
        if (res >= 0 && (size_t) res < sizeof(title))
                wpa_hexdump_key(MSG_MSGDUMP, title, key, *len);
@@ -1860,14 +1860,14 @@ int wpa_config_update_prio_list(struct wpa_config *config)
 static void eap_peer_config_free(struct eap_peer_config *eap)
 {
        os_free(eap->eap_methods);
-       os_free(eap->identity);
+       bin_clear_free(eap->identity, eap->identity_len);
        os_free(eap->anonymous_identity);
-       os_free(eap->password);
+       bin_clear_free(eap->password, eap->password_len);
        os_free(eap->ca_cert);
        os_free(eap->ca_path);
        os_free(eap->client_cert);
        os_free(eap->private_key);
-       os_free(eap->private_key_passwd);
+       str_clear_free(eap->private_key_passwd);
        os_free(eap->dh_file);
        os_free(eap->subject_match);
        os_free(eap->altsubject_match);
@@ -1876,7 +1876,7 @@ static void eap_peer_config_free(struct eap_peer_config *eap)
        os_free(eap->ca_path2);
        os_free(eap->client_cert2);
        os_free(eap->private_key2);
-       os_free(eap->private_key2_passwd);
+       str_clear_free(eap->private_key2_passwd);
        os_free(eap->dh_file2);
        os_free(eap->subject_match2);
        os_free(eap->altsubject_match2);
@@ -1884,7 +1884,7 @@ static void eap_peer_config_free(struct eap_peer_config *eap)
        os_free(eap->phase1);
        os_free(eap->phase2);
        os_free(eap->pcsc);
-       os_free(eap->pin);
+       str_clear_free(eap->pin);
        os_free(eap->engine_id);
        os_free(eap->key_id);
        os_free(eap->cert_id);
@@ -1892,13 +1892,13 @@ static void eap_peer_config_free(struct eap_peer_config *eap)
        os_free(eap->key2_id);
        os_free(eap->cert2_id);
        os_free(eap->ca_cert2_id);
-       os_free(eap->pin2);
+       str_clear_free(eap->pin2);
        os_free(eap->engine2_id);
        os_free(eap->otp);
        os_free(eap->pending_req_otp);
        os_free(eap->pac_file);
-       os_free(eap->new_password);
-       os_free(eap->external_sim_resp);
+       bin_clear_free(eap->new_password, eap->new_password_len);
+       str_clear_free(eap->external_sim_resp);
 }
 #endif /* IEEE8021X_EAPOL */
 
@@ -1915,7 +1915,8 @@ void wpa_config_free_ssid(struct wpa_ssid *ssid)
        struct psk_list_entry *psk;
 
        os_free(ssid->ssid);
-       os_free(ssid->passphrase);
+       os_memset(ssid->psk, 0, sizeof(ssid->psk));
+       str_clear_free(ssid->passphrase);
        os_free(ssid->ext_psk);
 #ifdef IEEE8021X_EAPOL
        eap_peer_config_free(&ssid->eap);
@@ -1942,14 +1943,14 @@ void wpa_config_free_cred(struct wpa_cred *cred)
        size_t i;
 
        os_free(cred->realm);
-       os_free(cred->username);
-       os_free(cred->password);
+       str_clear_free(cred->username);
+       str_clear_free(cred->password);
        os_free(cred->ca_cert);
        os_free(cred->client_cert);
        os_free(cred->private_key);
-       os_free(cred->private_key_passwd);
+       str_clear_free(cred->private_key_passwd);
        os_free(cred->imsi);
-       os_free(cred->milenage);
+       str_clear_free(cred->milenage);
        for (i = 0; i < cred->num_domain; i++)
                os_free(cred->domain[i]);
        os_free(cred->domain);
@@ -2019,7 +2020,7 @@ void wpa_config_free(struct wpa_config *config)
        os_free(config->pkcs11_engine_path);
        os_free(config->pkcs11_module_path);
        os_free(config->pcsc_reader);
-       os_free(config->pcsc_pin);
+       str_clear_free(config->pcsc_pin);
        os_free(config->driver_param);
        os_free(config->device_name);
        os_free(config->manufacturer);
@@ -2403,7 +2404,7 @@ char * wpa_config_get_no_key(struct wpa_ssid *ssid, const char *var)
                                        wpa_printf(MSG_DEBUG, "Do not allow "
                                                   "key_data field to be "
                                                   "exposed");
-                                       os_free(res);
+                                       str_clear_free(res);
                                        return os_strdup("*");
                                }
 
@@ -2549,7 +2550,7 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
 
        if (os_strcmp(var, "password") == 0 &&
            os_strncmp(value, "ext:", 4) == 0) {
-               os_free(cred->password);
+               str_clear_free(cred->password);
                cred->password = os_strdup(value);
                cred->ext_password = 1;
                return 0;
@@ -2612,13 +2613,13 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
        }
 
        if (os_strcmp(var, "username") == 0) {
-               os_free(cred->username);
+               str_clear_free(cred->username);
                cred->username = val;
                return 0;
        }
 
        if (os_strcmp(var, "password") == 0) {
-               os_free(cred->password);
+               str_clear_free(cred->password);
                cred->password = val;
                cred->ext_password = 0;
                return 0;
@@ -2643,7 +2644,7 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
        }
 
        if (os_strcmp(var, "private_key_passwd") == 0) {
-               os_free(cred->private_key_passwd);
+               str_clear_free(cred->private_key_passwd);
                cred->private_key_passwd = val;
                return 0;
        }
@@ -2655,7 +2656,7 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
        }
 
        if (os_strcmp(var, "milenage") == 0) {
-               os_free(cred->milenage);
+               str_clear_free(cred->milenage);
                cred->milenage = val;
                return 0;
        }
@@ -3207,7 +3208,7 @@ void wpa_config_free_blob(struct wpa_config_blob *blob)
 {
        if (blob) {
                os_free(blob->name);
-               os_free(blob->data);
+               bin_clear_free(blob->data, blob->len);
                os_free(blob);
        }
 }
index 0afc9ab8c1f1dba58b0d35a8d14619d34bfd463b..cf1b283ff67a151662a0e6b9ff554cb4e4edc9b6 100644 (file)
@@ -4395,7 +4395,7 @@ int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
                        wpa_s->reassociate = 1;
                break;
        case WPA_CTRL_REQ_EAP_PASSWORD:
-               os_free(eap->password);
+               bin_clear_free(eap->password, eap->password_len);
                eap->password = (u8 *) os_strdup(value);
                eap->password_len = os_strlen(value);
                eap->pending_req_password = 0;
@@ -4403,7 +4403,7 @@ int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
                        wpa_s->reassociate = 1;
                break;
        case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
-               os_free(eap->new_password);
+               bin_clear_free(eap->new_password, eap->new_password_len);
                eap->new_password = (u8 *) os_strdup(value);
                eap->new_password_len = os_strlen(value);
                eap->pending_req_new_password = 0;
@@ -4411,14 +4411,14 @@ int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
                        wpa_s->reassociate = 1;
                break;
        case WPA_CTRL_REQ_EAP_PIN:
-               os_free(eap->pin);
+               str_clear_free(eap->pin);
                eap->pin = os_strdup(value);
                eap->pending_req_pin = 0;
                if (ssid == wpa_s->current_ssid)
                        wpa_s->reassociate = 1;
                break;
        case WPA_CTRL_REQ_EAP_OTP:
-               os_free(eap->otp);
+               bin_clear_free(eap->otp, eap->otp_len);
                eap->otp = (u8 *) os_strdup(value);
                eap->otp_len = os_strlen(value);
                os_free(eap->pending_req_otp);
@@ -4426,14 +4426,14 @@ int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
                eap->pending_req_otp_len = 0;
                break;
        case WPA_CTRL_REQ_EAP_PASSPHRASE:
-               os_free(eap->private_key_passwd);
-               eap->private_key_passwd = (u8 *) os_strdup(value);
+               str_clear_free(eap->private_key_passwd);
+               eap->private_key_passwd = os_strdup(value);
                eap->pending_req_passphrase = 0;
                if (ssid == wpa_s->current_ssid)
                        wpa_s->reassociate = 1;
                break;
        case WPA_CTRL_REQ_SIM:
-               os_free(eap->external_sim_resp);
+               str_clear_free(eap->external_sim_resp);
                eap->external_sim_resp = os_strdup(value);
                break;
        default: