diff --git a/src/eap_peer/eap.c b/src/eap_peer/eap.c index 47cbbeed1..a2faeb2d2 100644 --- a/src/eap_peer/eap.c +++ b/src/eap_peer/eap.c @@ -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; diff --git a/src/eap_peer/eap_aka.c b/src/eap_peer/eap_aka.c index 41361c019..0662ae738 100644 --- a/src/eap_peer/eap_aka.c +++ b/src/eap_peer/eap_aka.c @@ -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); } diff --git a/src/eap_peer/eap_eke.c b/src/eap_peer/eap_eke.c index 0f4e53504..9fec66c06 100644 --- a/src/eap_peer/eap_eke.c +++ b/src/eap_peer/eap_eke.c @@ -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)); } diff --git a/src/eap_peer/eap_fast.c b/src/eap_peer/eap_fast.c index 127a0d9ed..0739187c1 100644 --- a/src/eap_peer/eap_fast.c +++ b/src/eap_peer/eap_fast.c @@ -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 && diff --git a/src/eap_peer/eap_gpsk.c b/src/eap_peer/eap_gpsk.c index 998ea06ef..c54bf1164 100644 --- a/src/eap_peer/eap_gpsk.c +++ b/src/eap_peer/eap_gpsk.c @@ -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)); } diff --git a/src/eap_peer/eap_ikev2.c b/src/eap_peer/eap_ikev2.c index 568a44804..c12b51933 100644 --- a/src/eap_peer/eap_ikev2.c +++ b/src/eap_peer/eap_ikev2.c @@ -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)); } diff --git a/src/eap_peer/eap_leap.c b/src/eap_peer/eap_leap.c index f4cd1250d..e0f8bcf6b 100644 --- a/src/eap_peer/eap_leap.c +++ b/src/eap_peer/eap_leap.c @@ -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; } diff --git a/src/eap_peer/eap_mschapv2.c b/src/eap_peer/eap_mschapv2.c index f2fcc3710..430c501bb 100644 --- a/src/eap_peer/eap_mschapv2.c +++ b/src/eap_peer/eap_mschapv2.c @@ -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; diff --git a/src/eap_peer/eap_pax.c b/src/eap_peer/eap_pax.c index f10a15b5a..1c111c28d 100644 --- a/src/eap_peer/eap_pax.c +++ b/src/eap_peer/eap_pax.c @@ -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)); } diff --git a/src/eap_peer/eap_peap.c b/src/eap_peer/eap_peap.c index 7740cf99f..472e861b0 100644 --- a/src/eap_peer/eap_peap.c +++ b/src/eap_peer/eap_peap.c @@ -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)) { diff --git a/src/eap_peer/eap_psk.c b/src/eap_peer/eap_psk.c index fc2a1b909..f01266354 100644 --- a/src/eap_peer/eap_psk.c +++ b/src/eap_peer/eap_psk.c @@ -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)); } diff --git a/src/eap_peer/eap_pwd.c b/src/eap_peer/eap_pwd.c index fec3224c5..bdcca0b81 100644 --- a/src/eap_peer/eap_pwd.c +++ b/src/eap_peer/eap_pwd.c @@ -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)); } diff --git a/src/eap_peer/eap_sake.c b/src/eap_peer/eap_sake.c index 85fe860c4..7d1490743 100644 --- a/src/eap_peer/eap_sake.c +++ b/src/eap_peer/eap_sake.c @@ -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)); } diff --git a/src/eap_peer/eap_sim.c b/src/eap_peer/eap_sim.c index 9e0c08fa5..bd06df78d 100644 --- a/src/eap_peer/eap_sim.c +++ b/src/eap_peer/eap_sim.c @@ -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); } diff --git a/src/eap_peer/eap_tls.c b/src/eap_peer/eap_tls.c index bb9f3f261..5aa3fd591 100644 --- a/src/eap_peer/eap_tls.c +++ b/src/eap_peer/eap_tls.c @@ -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)) { diff --git a/src/eap_peer/eap_ttls.c b/src/eap_peer/eap_ttls.c index 5091bf084..e110236ad 100644 --- a/src/eap_peer/eap_ttls.c +++ b/src/eap_peer/eap_ttls.c @@ -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)) {