]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
EAP peer: Clear keying material on deinit
authorJouni Malinen <j@w1.fi>
Sun, 29 Jun 2014 18:16:30 +0000 (21:16 +0300)
committerJouni Malinen <j@w1.fi>
Wed, 2 Jul 2014 09:38:48 +0000 (12:38 +0300)
Reduce the amount of time keying material (MSK, EMSK, temporary private
data) remains in memory in EAP methods. This provides additional
protection should there be any issues that could expose process memory
to external observers.

Signed-off-by: Jouni Malinen <j@w1.fi>
16 files changed:
src/eap_peer/eap.c
src/eap_peer/eap_aka.c
src/eap_peer/eap_eke.c
src/eap_peer/eap_fast.c
src/eap_peer/eap_gpsk.c
src/eap_peer/eap_ikev2.c
src/eap_peer/eap_leap.c
src/eap_peer/eap_mschapv2.c
src/eap_peer/eap_pax.c
src/eap_peer/eap_peap.c
src/eap_peer/eap_psk.c
src/eap_peer/eap_pwd.c
src/eap_peer/eap_sake.c
src/eap_peer/eap_sim.c
src/eap_peer/eap_tls.c
src/eap_peer/eap_ttls.c

index 47cbbeed13217c353e329b8145819048f9b7572b..a2faeb2d29f6ff0242f57cd2575c32d3b1abf47b 100644 (file)
@@ -92,6 +92,15 @@ static void eap_notify_status(struct eap_sm *sm, const char *status,
 }
 
 
+static void eap_sm_free_key(struct eap_sm *sm)
+{
+       if (sm->eapKeyData) {
+               bin_clear_free(sm->eapKeyData, sm->eapKeyDataLen);
+               sm->eapKeyData = NULL;
+       }
+}
+
+
 static void eap_deinit_prev_method(struct eap_sm *sm, const char *txt)
 {
        ext_password_free(sm->ext_pw_buf);
@@ -159,8 +168,7 @@ SM_STATE(EAP, INITIALIZE)
        eapol_set_int(sm, EAPOL_idleWhile, sm->ClientTimeout);
        eapol_set_bool(sm, EAPOL_eapSuccess, FALSE);
        eapol_set_bool(sm, EAPOL_eapFail, FALSE);
-       os_free(sm->eapKeyData);
-       sm->eapKeyData = NULL;
+       eap_sm_free_key(sm);
        os_free(sm->eapSessionId);
        sm->eapSessionId = NULL;
        sm->eapKeyAvailable = FALSE;
@@ -404,7 +412,7 @@ SM_STATE(EAP, METHOD)
 
        if (sm->m->isKeyAvailable && sm->m->getKey &&
            sm->m->isKeyAvailable(sm, sm->eap_method_priv)) {
-               os_free(sm->eapKeyData);
+               eap_sm_free_key(sm);
                sm->eapKeyData = sm->m->getKey(sm, sm->eap_method_priv,
                                               &sm->eapKeyDataLen);
                os_free(sm->eapSessionId);
@@ -1488,8 +1496,7 @@ void eap_sm_abort(struct eap_sm *sm)
        sm->lastRespData = NULL;
        wpabuf_free(sm->eapRespData);
        sm->eapRespData = NULL;
-       os_free(sm->eapKeyData);
-       sm->eapKeyData = NULL;
+       eap_sm_free_key(sm);
        os_free(sm->eapSessionId);
        sm->eapSessionId = NULL;
 
index 41361c0194056a47248a6525799ed848b15b9850..0662ae738367447325ba9e1b116a452ba1340ab4 100644 (file)
@@ -126,6 +126,21 @@ static void * eap_aka_prime_init(struct eap_sm *sm)
 #endif /* EAP_AKA_PRIME */
 
 
+static void eap_aka_clear_keys(struct eap_aka_data *data, int reauth)
+{
+       if (!reauth) {
+               os_memset(data->mk, 0, EAP_SIM_MK_LEN);
+               os_memset(data->k_aut, 0, EAP_AKA_PRIME_K_AUT_LEN);
+               os_memset(data->k_encr, 0, EAP_SIM_K_ENCR_LEN);
+               os_memset(data->k_re, 0, EAP_AKA_PRIME_K_RE_LEN);
+       }
+       os_memset(data->msk, 0, EAP_SIM_KEYING_DATA_LEN);
+       os_memset(data->emsk, 0, EAP_EMSK_LEN);
+       os_memset(data->autn, 0, EAP_AKA_AUTN_LEN);
+       os_memset(data->auts, 0, EAP_AKA_AUTS_LEN);
+}
+
+
 static void eap_aka_deinit(struct eap_sm *sm, void *priv)
 {
        struct eap_aka_data *data = priv;
@@ -135,6 +150,7 @@ static void eap_aka_deinit(struct eap_sm *sm, void *priv)
                os_free(data->last_eap_identity);
                wpabuf_free(data->id_msgs);
                os_free(data->network_name);
+               eap_aka_clear_keys(data, 0);
                os_free(data);
        }
 }
@@ -1373,6 +1389,7 @@ static void eap_aka_deinit_for_reauth(struct eap_sm *sm, void *priv)
        data->id_msgs = NULL;
        data->use_result_ind = 0;
        data->kdf_negotiation = 0;
+       eap_aka_clear_keys(data, 1);
 }
 
 
index 0f4e53504a1bd48c01ae159dd1b357ac626efa41..9fec66c0686795b0d93051ed036e6d8c56a107df 100644 (file)
@@ -138,7 +138,7 @@ static void eap_eke_deinit(struct eap_sm *sm, void *priv)
        os_free(data->serverid);
        os_free(data->peerid);
        wpabuf_free(data->msgs);
-       os_free(data);
+       bin_clear_free(data, sizeof(*data));
 }
 
 
index 127a0d9ed5d699634f8786c57430caa21aa431f6..0739187c119d049509d0b7c90792527f137ed021 100644 (file)
@@ -250,6 +250,8 @@ static void eap_fast_deinit(struct eap_sm *sm, void *priv)
                pac = pac->next;
                eap_fast_free_pac(prev);
        }
+       os_memset(data->key_data, 0, EAP_FAST_KEY_LEN);
+       os_memset(data->emsk, 0, EAP_EMSK_LEN);
        os_free(data->session_id);
        wpabuf_free(data->pending_phase2_req);
        os_free(data);
@@ -1636,6 +1638,8 @@ static void * eap_fast_init_for_reauth(struct eap_sm *sm, void *priv)
                os_free(data);
                return NULL;
        }
+       os_memset(data->key_data, 0, EAP_FAST_KEY_LEN);
+       os_memset(data->emsk, 0, EAP_EMSK_LEN);
        os_free(data->session_id);
        data->session_id = NULL;
        if (data->phase2_priv && data->phase2_method &&
index 998ea06ef89ad8772761671230075ef02f6e5517..c54bf116477c8a76f058b33c34f2edb5b72f2256 100644 (file)
@@ -134,8 +134,11 @@ static void eap_gpsk_deinit(struct eap_sm *sm, void *priv)
        struct eap_gpsk_data *data = priv;
        os_free(data->id_server);
        os_free(data->id_peer);
-       os_free(data->psk);
-       os_free(data);
+       if (data->psk) {
+               os_memset(data->psk, 0, data->psk_len);
+               os_free(data->psk);
+       }
+       bin_clear_free(data, sizeof(*data));
 }
 
 
index 568a44804ac1a60cc841d823b7eb25a3499b80f3..c12b51933e8b4aa1869625af8d1d8a8605edf5f6 100644 (file)
@@ -113,7 +113,7 @@ static void eap_ikev2_deinit(struct eap_sm *sm, void *priv)
        wpabuf_free(data->in_buf);
        wpabuf_free(data->out_buf);
        ikev2_responder_deinit(&data->ikev2);
-       os_free(data);
+       bin_clear_free(data, sizeof(*data));
 }
 
 
index f4cd1250d7fa71be70caac1a5aa64da2ced8334e..e0f8bcf6b0df7fe27134268965e53633ce10fdad 100644 (file)
@@ -383,6 +383,9 @@ static u8 * eap_leap_getKey(struct eap_sm *sm, void *priv, size_t *len)
        wpa_hexdump_key(MSG_DEBUG, "EAP-LEAP: master key", key, LEAP_KEY_LEN);
        *len = LEAP_KEY_LEN;
 
+       os_memset(pw_hash, 0, sizeof(pw_hash));
+       os_memset(pw_hash_hash, 0, sizeof(pw_hash_hash));
+
        return key;
 }
 
index f2fcc37108d87f6f399b05d87bfdfd4de2b9850a..430c501bb588e607618d3fa1ae3aa13b0a948ab8 100644 (file)
@@ -140,7 +140,7 @@ static void eap_mschapv2_deinit(struct eap_sm *sm, void *priv)
        os_free(data->peer_challenge);
        os_free(data->auth_challenge);
        wpabuf_free(data->prev_challenge);
-       os_free(data);
+       bin_clear_free(data, sizeof(*data));
 }
 
 
@@ -303,7 +303,7 @@ static void eap_mschapv2_password_changed(struct eap_sm *sm,
                        WPA_EVENT_PASSWORD_CHANGED
                        "EAP-MSCHAPV2: Password changed successfully");
                data->prev_error = 0;
-               os_free(config->password);
+               bin_clear_free(config->password, config->password_len);
                if (config->flags & EAP_CONFIG_FLAGS_EXT_PASSWORD) {
                        /* TODO: update external storage */
                } else if (config->flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH) {
@@ -313,11 +313,13 @@ static void eap_mschapv2_password_changed(struct eap_sm *sm,
                            nt_password_hash(config->new_password,
                                             config->new_password_len,
                                             config->password)) {
-                               os_free(config->password);
+                               bin_clear_free(config->password,
+                                              config->password_len);
                                config->password = NULL;
                                config->password_len = 0;
                        }
-                       os_free(config->new_password);
+                       bin_clear_free(config->new_password,
+                                      config->new_password_len);
                } else {
                        config->password = config->new_password;
                        config->password_len = config->new_password_len;
index f10a15b5aabd0667b59b49dd239031ef61bf5482..1c111c28d60c6860d192f4123cb275c983d282db 100644 (file)
@@ -86,7 +86,7 @@ static void eap_pax_deinit(struct eap_sm *sm, void *priv)
 {
        struct eap_pax_data *data = priv;
        os_free(data->cid);
-       os_free(data);
+       bin_clear_free(data, sizeof(*data));
 }
 
 
index 7740cf99fff65b1de92deaf8099bff1d0132e64c..472e861b0fc661f8bd0ee51307690c702de41a48 100644 (file)
@@ -170,6 +170,15 @@ static void * eap_peap_init(struct eap_sm *sm)
 }
 
 
+static void eap_peap_free_key(struct eap_peap_data *data)
+{
+       if (data->key_data) {
+               bin_clear_free(data->key_data, EAP_TLS_KEY_LEN);
+               data->key_data = NULL;
+       }
+}
+
+
 static void eap_peap_deinit(struct eap_sm *sm, void *priv)
 {
        struct eap_peap_data *data = priv;
@@ -179,7 +188,7 @@ static void eap_peap_deinit(struct eap_sm *sm, void *priv)
                data->phase2_method->deinit(sm, data->phase2_priv);
        os_free(data->phase2_types);
        eap_peer_tls_ssl_deinit(sm, &data->ssl);
-       os_free(data->key_data);
+       eap_peap_free_key(data);
        os_free(data->session_id);
        wpabuf_free(data->pending_phase2_req);
        os_free(data);
@@ -1005,7 +1014,7 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv,
                        char *label;
                        wpa_printf(MSG_DEBUG,
                                   "EAP-PEAP: TLS done, proceed to Phase 2");
-                       os_free(data->key_data);
+                       eap_peap_free_key(data);
                        /* draft-josefsson-ppext-eap-tls-eap-05.txt
                         * specifies that PEAPv1 would use "client PEAP
                         * encryption" as the label. However, most existing
@@ -1115,8 +1124,7 @@ static void eap_peap_deinit_for_reauth(struct eap_sm *sm, void *priv)
 static void * eap_peap_init_for_reauth(struct eap_sm *sm, void *priv)
 {
        struct eap_peap_data *data = priv;
-       os_free(data->key_data);
-       data->key_data = NULL;
+       eap_peap_free_key(data);
        os_free(data->session_id);
        data->session_id = NULL;
        if (eap_peer_tls_reauth_init(sm, &data->ssl)) {
index fc2a1b9093d796503d5ae40629ed2e6289f82c2d..f01266354e904d63d2555dbabbc6a2feeb27b940 100644 (file)
@@ -76,7 +76,7 @@ static void eap_psk_deinit(struct eap_sm *sm, void *priv)
        struct eap_psk_data *data = priv;
        os_free(data->id_s);
        os_free(data->id_p);
-       os_free(data);
+       bin_clear_free(data, sizeof(*data));
 }
 
 
index fec3224c567d174edd3ef4c974ac25e7a10c240d..bdcca0b815bbc52ccf9c787e4cc3c24559b286ef 100644 (file)
@@ -157,7 +157,7 @@ static void eap_pwd_deinit(struct eap_sm *sm, void *priv)
        EC_POINT_free(data->server_element);
        os_free(data->id_peer);
        os_free(data->id_server);
-       os_free(data->password);
+       bin_clear_free(data->password, data->password_len);
        if (data->grp) {
                EC_GROUP_free(data->grp->group);
                EC_POINT_free(data->grp->pwe);
@@ -167,7 +167,7 @@ static void eap_pwd_deinit(struct eap_sm *sm, void *priv)
        }
        wpabuf_free(data->inbuf);
        wpabuf_free(data->outbuf);
-       os_free(data);
+       bin_clear_free(data, sizeof(*data));
 }
 
 
index 85fe860c4f2729504137170498e7620c0ebd72f4..7d14907433e5032d2e1067ed02b94820f6f21112 100644 (file)
@@ -108,7 +108,7 @@ static void eap_sake_deinit(struct eap_sm *sm, void *priv)
        struct eap_sake_data *data = priv;
        os_free(data->serverid);
        os_free(data->peerid);
-       os_free(data);
+       bin_clear_free(data, sizeof(*data));
 }
 
 
index 9e0c08fa542a07aa2b058edbcdbfcff24fef83e8..bd06df78db4c443b0a70b91cb35cce1530d75c64 100644 (file)
@@ -130,6 +130,20 @@ static void * eap_sim_init(struct eap_sm *sm)
 }
 
 
+static void eap_sim_clear_keys(struct eap_sim_data *data, int reauth)
+{
+       if (!reauth) {
+               os_memset(data->mk, 0, EAP_SIM_MK_LEN);
+               os_memset(data->k_aut, 0, EAP_SIM_K_AUT_LEN);
+               os_memset(data->k_encr, 0, EAP_SIM_K_ENCR_LEN);
+       }
+       os_memset(data->kc, 0, 3 * EAP_SIM_KC_LEN);
+       os_memset(data->sres, 0, 3 * EAP_SIM_SRES_LEN);
+       os_memset(data->msk, 0, EAP_SIM_KEYING_DATA_LEN);
+       os_memset(data->emsk, 0, EAP_EMSK_LEN);
+}
+
+
 static void eap_sim_deinit(struct eap_sm *sm, void *priv)
 {
        struct eap_sim_data *data = priv;
@@ -138,6 +152,7 @@ static void eap_sim_deinit(struct eap_sm *sm, void *priv)
                os_free(data->pseudonym);
                os_free(data->reauth_id);
                os_free(data->last_eap_identity);
+               eap_sim_clear_keys(data, 0);
                os_free(data);
        }
 }
@@ -1110,6 +1125,7 @@ static void eap_sim_deinit_for_reauth(struct eap_sm *sm, void *priv)
        struct eap_sim_data *data = priv;
        eap_sim_clear_identities(sm, data, CLEAR_EAP_ID);
        data->use_result_ind = 0;
+       eap_sim_clear_keys(data, 1);
 }
 
 
index bb9f3f261149318219c24f3dc248c0485209f4fe..5aa3fd5912563570b63315713e7d12e86fd02b02 100644 (file)
@@ -125,13 +125,22 @@ static void * eap_wfa_unauth_tls_init(struct eap_sm *sm)
 #endif /* CONFIG_HS20 */
 
 
+static void eap_tls_free_key(struct eap_tls_data *data)
+{
+       if (data->key_data) {
+               bin_clear_free(data->key_data, EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
+               data->key_data = NULL;
+       }
+}
+
+
 static void eap_tls_deinit(struct eap_sm *sm, void *priv)
 {
        struct eap_tls_data *data = priv;
        if (data == NULL)
                return;
        eap_peer_tls_ssl_deinit(sm, &data->ssl);
-       os_free(data->key_data);
+       eap_tls_free_key(data);
        os_free(data->session_id);
        os_free(data);
 }
@@ -181,7 +190,7 @@ static void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data,
        ret->methodState = METHOD_DONE;
        ret->decision = DECISION_UNCOND_SUCC;
 
-       os_free(data->key_data);
+       eap_tls_free_key(data);
        data->key_data = eap_peer_tls_derive_key(sm, &data->ssl,
                                                 "client EAP encryption",
                                                 EAP_TLS_KEY_LEN +
@@ -267,8 +276,7 @@ static void eap_tls_deinit_for_reauth(struct eap_sm *sm, void *priv)
 static void * eap_tls_init_for_reauth(struct eap_sm *sm, void *priv)
 {
        struct eap_tls_data *data = priv;
-       os_free(data->key_data);
-       data->key_data = NULL;
+       eap_tls_free_key(data);
        os_free(data->session_id);
        data->session_id = NULL;
        if (eap_peer_tls_reauth_init(sm, &data->ssl)) {
index 5091bf0844bab1ef0c7ee46f89e3614437ee3cfd..e110236ad96f379fb1a65bb582ce436f7f43ece4 100644 (file)
@@ -133,6 +133,15 @@ static void eap_ttls_phase2_eap_deinit(struct eap_sm *sm,
 }
 
 
+static void eap_ttls_free_key(struct eap_ttls_data *data)
+{
+       if (data->key_data) {
+               bin_clear_free(data->key_data, EAP_TLS_KEY_LEN);
+               data->key_data = NULL;
+       }
+}
+
+
 static void eap_ttls_deinit(struct eap_sm *sm, void *priv)
 {
        struct eap_ttls_data *data = priv;
@@ -141,7 +150,7 @@ static void eap_ttls_deinit(struct eap_sm *sm, void *priv)
        eap_ttls_phase2_eap_deinit(sm, data);
        os_free(data->phase2_eap_types);
        eap_peer_tls_ssl_deinit(sm, &data->ssl);
-       os_free(data->key_data);
+       eap_ttls_free_key(data);
        os_free(data->session_id);
        wpabuf_free(data->pending_phase2_req);
        os_free(data);
@@ -213,7 +222,7 @@ static int eap_ttls_avp_encapsulate(struct wpabuf **resp, u32 avp_code,
 static int eap_ttls_v0_derive_key(struct eap_sm *sm,
                                  struct eap_ttls_data *data)
 {
-       os_free(data->key_data);
+       eap_ttls_free_key(data);
        data->key_data = eap_peer_tls_derive_key(sm, &data->ssl,
                                                 "ttls keying material",
                                                 EAP_TLS_KEY_LEN);
@@ -1540,8 +1549,7 @@ static void eap_ttls_deinit_for_reauth(struct eap_sm *sm, void *priv)
 static void * eap_ttls_init_for_reauth(struct eap_sm *sm, void *priv)
 {
        struct eap_ttls_data *data = priv;
-       os_free(data->key_data);
-       data->key_data = NULL;
+       eap_ttls_free_key(data);
        os_free(data->session_id);
        data->session_id = NULL;
        if (eap_peer_tls_reauth_init(sm, &data->ssl)) {