From f4d7329ae661aed22cb72dd5d00fdd57b31ae26b Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 29 Jun 2014 21:16:30 +0300 Subject: [PATCH] EAP peer: Clear keying material on deinit 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 --- components/wpa_supplicant/src/eap_peer/eap.c | 10 ++++++++++ .../wpa_supplicant/src/eap_peer/eap_mschapv2.c | 7 ++++--- .../wpa_supplicant/src/eap_peer/eap_peap.c | 16 ++++++++++++---- components/wpa_supplicant/src/eap_peer/eap_tls.c | 13 +++++++++++-- .../wpa_supplicant/src/eap_peer/eap_ttls.c | 16 ++++++++++++---- 5 files changed, 49 insertions(+), 13 deletions(-) diff --git a/components/wpa_supplicant/src/eap_peer/eap.c b/components/wpa_supplicant/src/eap_peer/eap.c index 458b077572..2658ad211b 100644 --- a/components/wpa_supplicant/src/eap_peer/eap.c +++ b/components/wpa_supplicant/src/eap_peer/eap.c @@ -316,6 +316,15 @@ int eap_peer_register_methods(void) return ret; } +static void eap_sm_free_key(struct eap_sm *sm) +{ + if (sm->eapKeyData) { + bin_clear_free(sm->eapKeyData, sm->eapKeyDataLen); + sm->eapKeyData = NULL; + } +} + + void eap_deinit_prev_method(struct eap_sm *sm, const char *txt) { if (sm->m == NULL || sm->eap_method_priv == NULL) @@ -826,6 +835,7 @@ void eap_sm_abort(struct eap_sm *sm) { wpabuf_free(sm->lastRespData); sm->lastRespData = NULL; + eap_sm_free_key(sm); } /** diff --git a/components/wpa_supplicant/src/eap_peer/eap_mschapv2.c b/components/wpa_supplicant/src/eap_peer/eap_mschapv2.c index 67df2472c0..ab536d1596 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_mschapv2.c +++ b/components/wpa_supplicant/src/eap_peer/eap_mschapv2.c @@ -87,7 +87,7 @@ 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)); } static void * @@ -285,7 +285,7 @@ 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) { @@ -296,7 +296,8 @@ eap_mschapv2_password_changed(struct eap_sm *sm, config->new_password_len, config->password); } - 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/components/wpa_supplicant/src/eap_peer/eap_peap.c b/components/wpa_supplicant/src/eap_peer/eap_peap.c index ecd2a39b29..3fe6ab1b8d 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_peap.c +++ b/components/wpa_supplicant/src/eap_peer/eap_peap.c @@ -71,6 +71,15 @@ struct eap_peap_data { }; +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 int eap_peap_parse_phase1(struct eap_peap_data *data, const char *phase1) @@ -198,7 +207,7 @@ 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); wpabuf_free(data->pending_resp); @@ -1178,7 +1187,7 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv, if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { char label[24] = {0}; 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 @@ -1294,8 +1303,7 @@ 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/components/wpa_supplicant/src/eap_peer/eap_tls.c b/components/wpa_supplicant/src/eap_peer/eap_tls.c index a4da54c606..ec16b1eb68 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_tls.c +++ b/components/wpa_supplicant/src/eap_peer/eap_tls.c @@ -60,13 +60,22 @@ static void * eap_tls_init(struct eap_sm *sm) } +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); wpabuf_free(data->pending_resp); os_free(data); @@ -135,7 +144,7 @@ static void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data, 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, label, EAP_TLS_KEY_LEN + EAP_EMSK_LEN); diff --git a/components/wpa_supplicant/src/eap_peer/eap_ttls.c b/components/wpa_supplicant/src/eap_peer/eap_ttls.c index 2e4c9f84d3..a78fece8ee 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_ttls.c +++ b/components/wpa_supplicant/src/eap_peer/eap_ttls.c @@ -127,6 +127,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; @@ -135,7 +144,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); wpabuf_free(data->pending_resp); @@ -208,7 +217,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); @@ -1607,8 +1616,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)) {