From 5c0fb109028d25a2a0ea348d40fa22a423ce24f5 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 12 Dec 2015 18:16:54 +0200 Subject: [PATCH 01/35] EAP peer: External server certificate chain validation This adds support for optional functionality to validate server certificate chain in TLS-based EAP methods in an external program. wpa_supplicant control interface is used to indicate when such validation is needed and what the result of the external validation is. This external validation can extend or replace the internal validation. When ca_cert or ca_path parameter is set, the internal validation is used. If these parameters are omitted, only the external validation is used. It needs to be understood that leaving those parameters out will disable most of the validation steps done with the TLS library and that configuration is not really recommend. By default, the external validation is not used. It can be enabled by addingtls_ext_cert_check=1 into the network profile phase1 parameter. When enabled, external validation is required through the CTRL-REQ/RSP mechanism similarly to other EAP authentication parameters through the control interface. The request to perform external validation is indicated by the following event: CTRL-REQ-EXT_CERT_CHECK-:External server certificate validation needed for SSID Before that event, the server certificate chain is provided with the CTRL-EVENT-EAP-PEER-CERT events that include the cert= parameter. depth=# indicates which certificate is in question (0 for the server certificate, 1 for its issues, and so on). The result of the external validation is provided with the following command: CTRL-RSP-EXT_CERT_CHECK-: It should be noted that this is currently enabled only for OpenSSL (and BoringSSL/LibreSSL). Due to the constraints in the library API, the validation result from external processing cannot be reported cleanly with TLS alert. In other words, if the external validation reject the server certificate chain, the pending TLS handshake is terminated without sending more messages to the server. Signed-off-by: Jouni Malinen --- components/wpa_supplicant/src/common/defs.h | 1 + components/wpa_supplicant/src/eap_peer/eap.c | 10 ++-- .../wpa_supplicant/src/eap_peer/eap_peap.c | 44 ++++++++++++++++- .../wpa_supplicant/src/eap_peer/eap_tls.c | 38 ++++++++++++++- .../wpa_supplicant/src/eap_peer/eap_ttls.c | 48 ++++++++++++++++++- 5 files changed, 134 insertions(+), 7 deletions(-) diff --git a/components/wpa_supplicant/src/common/defs.h b/components/wpa_supplicant/src/common/defs.h index 99759b3c6f..543f1bbd6b 100644 --- a/components/wpa_supplicant/src/common/defs.h +++ b/components/wpa_supplicant/src/common/defs.h @@ -369,6 +369,7 @@ enum wpa_ctrl_req_type { WPA_CTRL_REQ_EAP_PASSPHRASE, WPA_CTRL_REQ_SIM, WPA_CTRL_REQ_PSK_PASSPHRASE, + WPA_CTRL_REQ_EXT_CERT_CHECK, NUM_WPA_CTRL_REQS }; diff --git a/components/wpa_supplicant/src/eap_peer/eap.c b/components/wpa_supplicant/src/eap_peer/eap.c index bce12af1fc..458b077572 100644 --- a/components/wpa_supplicant/src/eap_peer/eap.c +++ b/components/wpa_supplicant/src/eap_peer/eap.c @@ -71,6 +71,8 @@ int (*esp_crt_bundle_attach_fn)(void *conf); void eap_peer_config_deinit(struct eap_sm *sm); void eap_peer_blob_deinit(struct eap_sm *sm); void eap_deinit_prev_method(struct eap_sm *sm, const char *txt); +static void eap_sm_request(struct eap_sm *sm, enum wpa_ctrl_req_type field, + const char *msg, size_t msglen); #ifdef EAP_PEER_METHOD static struct eap_method *eap_methods = NULL; @@ -713,10 +715,10 @@ _out: return ret; } -#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG) static void eap_sm_request(struct eap_sm *sm, enum wpa_ctrl_req_type field, const char *msg, size_t msglen) { +#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG) struct eap_peer_config *config; if (sm == NULL) @@ -741,14 +743,14 @@ static void eap_sm_request(struct eap_sm *sm, enum wpa_ctrl_req_type field, case WPA_CTRL_REQ_EAP_PASSPHRASE: config->pending_req_passphrase++; break; + case WPA_CTRL_REQ_EXT_CERT_CHECK: + break; default: return; } -} -#else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ -#define eap_sm_request(sm, type, msg, msglen) do { } while (0) #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ +} const char * eap_sm_get_method_name(struct eap_sm *sm) { diff --git a/components/wpa_supplicant/src/eap_peer/eap_peap.c b/components/wpa_supplicant/src/eap_peer/eap_peap.c index 744a6bb6ae..ecd2a39b29 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_peap.c +++ b/components/wpa_supplicant/src/eap_peer/eap_peap.c @@ -1,6 +1,6 @@ /* * EAP peer method: EAP-PEAP (draft-josefsson-pppext-eap-tls-eap-10.txt) - * Copyright (c) 2004-2008, Jouni Malinen + * Copyright (c) 2004-2015, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -59,6 +59,7 @@ struct eap_peap_data { size_t id_len; struct wpabuf *pending_phase2_req; + struct wpabuf *pending_resp; enum { NO_BINDING, OPTIONAL_BINDING, REQUIRE_BINDING } crypto_binding; int crypto_binding_used; u8 binding_nonce[32]; @@ -200,6 +201,7 @@ eap_peap_deinit(struct eap_sm *sm, void *priv) os_free(data->key_data); os_free(data->session_id); wpabuf_free(data->pending_phase2_req); + wpabuf_free(data->pending_resp); os_free(data); } @@ -1122,6 +1124,34 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv, wpabuf_set(&msg, pos, left); res = eap_peap_decrypt(sm, data, ret, req, &msg, &resp); } else { + if (sm->waiting_ext_cert_check && data->pending_resp) { + struct eap_peer_config *config = eap_get_config(sm); + + if (config->pending_ext_cert_check == + EXT_CERT_CHECK_GOOD) { + wpa_printf(MSG_DEBUG, + "EAP-PEAP: External certificate check succeeded - continue handshake"); + resp = data->pending_resp; + data->pending_resp = NULL; + sm->waiting_ext_cert_check = 0; + return resp; + } + + if (config->pending_ext_cert_check == + EXT_CERT_CHECK_BAD) { + wpa_printf(MSG_DEBUG, + "EAP-PEAP: External certificate check failed - force authentication failure"); + ret->methodState = METHOD_DONE; + ret->decision = DECISION_FAIL; + sm->waiting_ext_cert_check = 0; + return NULL; + } + + wpa_printf(MSG_DEBUG, + "EAP-PEAP: Continuing to wait external server certificate validation"); + return NULL; + } + res = eap_peer_tls_process_helper(sm, &data->ssl, EAP_TYPE_PEAP, data->peap_version, id, pos, @@ -1135,6 +1165,16 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv, return resp; } + + if (sm->waiting_ext_cert_check) { + wpa_printf(MSG_DEBUG, + "EAP-PEAP: Waiting external server certificate validation"); + wpabuf_free(data->pending_resp); + data->pending_resp = resp; + return NULL; + } + + 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"); @@ -1244,6 +1284,8 @@ eap_peap_deinit_for_reauth(struct eap_sm *sm, void *priv) struct eap_peap_data *data = priv; wpabuf_free(data->pending_phase2_req); data->pending_phase2_req = NULL; + wpabuf_free(data->pending_resp); + data->pending_resp = NULL; data->crypto_binding_used = 0; } diff --git a/components/wpa_supplicant/src/eap_peer/eap_tls.c b/components/wpa_supplicant/src/eap_peer/eap_tls.c index 0da0c7f86a..3f7e89e260 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_tls.c +++ b/components/wpa_supplicant/src/eap_peer/eap_tls.c @@ -1,6 +1,6 @@ /* * EAP peer method: EAP-TLS (RFC 2716) - * Copyright (c) 2004-2008, 2012, Jouni Malinen + * Copyright (c) 2004-2008, 2012-2015, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -27,6 +27,7 @@ struct eap_tls_data { size_t id_len; void *ssl_ctx; u8 eap_type; + struct wpabuf *pending_resp; }; @@ -67,6 +68,7 @@ static void eap_tls_deinit(struct eap_sm *sm, void *priv) eap_peer_tls_ssl_deinit(sm, &data->ssl); os_free(data->key_data); os_free(data->session_id); + wpabuf_free(data->pending_resp); os_free(data); } @@ -154,6 +156,32 @@ static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv, const u8 *pos; struct eap_tls_data *data = priv; + if (sm->waiting_ext_cert_check && data->pending_resp) { + struct eap_peer_config *config = eap_get_config(sm); + + if (config->pending_ext_cert_check == EXT_CERT_CHECK_GOOD) { + wpa_printf(MSG_DEBUG, + "EAP-TLS: External certificate check succeeded - continue handshake"); + resp = data->pending_resp; + data->pending_resp = NULL; + sm->waiting_ext_cert_check = 0; + return resp; + } + + if (config->pending_ext_cert_check == EXT_CERT_CHECK_BAD) { + wpa_printf(MSG_DEBUG, + "EAP-TLS: External certificate check failed - force authentication failure"); + ret->methodState = METHOD_DONE; + ret->decision = DECISION_FAIL; + sm->waiting_ext_cert_check = 0; + return NULL; + } + + wpa_printf(MSG_DEBUG, + "EAP-TLS: Continuing to wait external server certificate validation"); + return NULL; + } + pos = eap_peer_tls_process_init(sm, &data->ssl, data->eap_type, ret, reqData, &left, &flags); if (pos == NULL) @@ -174,6 +202,14 @@ static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv, return eap_tls_failure(sm, data, ret, res, resp, id); } + if (sm->waiting_ext_cert_check) { + wpa_printf(MSG_DEBUG, + "EAP-TLS: Waiting external server certificate validation"); + wpabuf_free(data->pending_resp); + data->pending_resp = resp; + return NULL; + } + if (tls_connection_established(data->ssl_ctx, data->ssl.conn)) eap_tls_success(sm, data, ret); diff --git a/components/wpa_supplicant/src/eap_peer/eap_ttls.c b/components/wpa_supplicant/src/eap_peer/eap_ttls.c index 243544a2c2..84cf9260e0 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_ttls.c +++ b/components/wpa_supplicant/src/eap_peer/eap_ttls.c @@ -1,6 +1,6 @@ /* * EAP peer method: EAP-TTLS (RFC 5281) - * Copyright (c) 2004-2011, Jouni Malinen + * Copyright (c) 2004-2015, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -59,6 +59,7 @@ struct eap_ttls_data { size_t id_len; struct wpabuf *pending_phase2_req; + struct wpabuf *pending_resp; #ifdef EAP_TNC int ready_for_tnc; @@ -137,6 +138,7 @@ static void eap_ttls_deinit(struct eap_sm *sm, void *priv) os_free(data->key_data); os_free(data->session_id); wpabuf_free(data->pending_phase2_req); + wpabuf_free(data->pending_resp); os_free(data); } @@ -1393,10 +1395,52 @@ static int eap_ttls_process_handshake(struct eap_sm *sm, { int res; + if (sm->waiting_ext_cert_check && data->pending_resp) { + struct eap_peer_config *config = eap_get_config(sm); + + if (config->pending_ext_cert_check == EXT_CERT_CHECK_GOOD) { + wpa_printf(MSG_DEBUG, + "EAP-TTLS: External certificate check succeeded - continue handshake"); + *out_data = data->pending_resp; + data->pending_resp = NULL; + sm->waiting_ext_cert_check = 0; + return 0; + } + + if (config->pending_ext_cert_check == EXT_CERT_CHECK_BAD) { + wpa_printf(MSG_DEBUG, + "EAP-TTLS: External certificate check failed - force authentication failure"); + ret->methodState = METHOD_DONE; + ret->decision = DECISION_FAIL; + sm->waiting_ext_cert_check = 0; + return 0; + } + + wpa_printf(MSG_DEBUG, + "EAP-TTLS: Continuing to wait external server certificate validation"); + return 0; + } + res = eap_peer_tls_process_helper(sm, &data->ssl, EAP_TYPE_TTLS, data->ttls_version, identifier, in_data, in_len, out_data); + if (res < 0) { + wpa_printf(MSG_DEBUG, "EAP-TTLS: TLS processing failed"); + ret->methodState = METHOD_DONE; + ret->decision = DECISION_FAIL; + return -1; + } + + if (sm->waiting_ext_cert_check) { + wpa_printf(MSG_DEBUG, + "EAP-TTLS: Waiting external server certificate validation"); + wpabuf_free(data->pending_resp); + data->pending_resp = *out_data; + *out_data = NULL; + return 0; + } + if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { wpa_printf(MSG_DEBUG, "EAP-TTLS: TLS done, proceed to " "Phase 2"); @@ -1537,6 +1581,8 @@ static void eap_ttls_deinit_for_reauth(struct eap_sm *sm, void *priv) struct eap_ttls_data *data = priv; wpabuf_free(data->pending_phase2_req); data->pending_phase2_req = NULL; + wpabuf_free(data->pending_resp); + data->pending_resp = NULL; #ifdef EAP_TNC data->ready_for_tnc = 0; data->tnc_started = 0; From a539c63d68ba9a0e205750193a6acc497c914fae Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Thu, 8 Jun 2017 11:17:59 +0300 Subject: [PATCH 02/35] EAP-TTLS: Fix possible memory leak in eap_ttls_phase2_request_mschap() The msg buffer needs to be freed on these two error paths. Signed-off-by: Ilan Peer --- .../wpa_supplicant/src/eap_peer/eap_ttls.c | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/components/wpa_supplicant/src/eap_peer/eap_ttls.c b/components/wpa_supplicant/src/eap_peer/eap_ttls.c index 84cf9260e0..2e4c9f84d3 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_ttls.c +++ b/components/wpa_supplicant/src/eap_peer/eap_ttls.c @@ -573,12 +573,26 @@ static int eap_ttls_phase2_request_mschap(struct eap_sm *sm, os_memset(pos, 0, 24); /* LM-Response */ pos += 24; if (pwhash) { - challenge_response(challenge, password, pos); /* NT-Response */ + /* NT-Response */ + if (challenge_response(challenge, password, pos)) { + wpa_printf(MSG_ERROR, + "EAP-TTLS/MSCHAP: Failed derive password hash"); + wpabuf_free(msg); + return -1; + } + wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: MSCHAP password hash", password, 16); } else { - nt_challenge_response(challenge, password, password_len, - pos); /* NT-Response */ + /* NT-Response */ + if (nt_challenge_response(challenge, password, password_len, + pos)) { + wpa_printf(MSG_ERROR, + "EAP-TTLS/MSCHAP: Failed derive password"); + wpabuf_free(msg); + return -1; + } + wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: MSCHAP password", password, password_len); } From 77d87edbb23d4f90d33121d79aa66f499375c913 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 1 May 2018 17:45:37 +0300 Subject: [PATCH 03/35] EAP-TLS peer: Determine whether TLS v1.3 or newer is used This is needed to be able to handle different key derivation and message handshakes in EAP implementation. Signed-off-by: Jouni Malinen --- components/wpa_supplicant/src/eap_peer/eap_tls_common.c | 8 ++++++++ components/wpa_supplicant/src/eap_peer/eap_tls_common.h | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/components/wpa_supplicant/src/eap_peer/eap_tls_common.c b/components/wpa_supplicant/src/eap_peer/eap_tls_common.c index b3ebfa7362..60ef6096bd 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_tls_common.c +++ b/components/wpa_supplicant/src/eap_peer/eap_tls_common.c @@ -616,6 +616,8 @@ int eap_peer_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data, */ int res = eap_tls_process_input(sm, data, in_data, in_len, out_data); + char buf[20]; + if (res) { /* * Input processing failed (res = -1) or more data is @@ -628,6 +630,12 @@ int eap_peer_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data, * The incoming message has been reassembled and processed. The * response was allocated into data->tls_out buffer. */ + + if (tls_get_version(data->ssl_ctx, data->conn, + buf, sizeof(buf)) == 0) { + wpa_printf(MSG_DEBUG, "SSL: Using TLS version %s", buf); + data->tls_v13 = os_strcmp(buf, "TLSv1.3") == 0; + } } if (data->tls_out == NULL) { diff --git a/components/wpa_supplicant/src/eap_peer/eap_tls_common.h b/components/wpa_supplicant/src/eap_peer/eap_tls_common.h index 50390c4ce0..fea1458ee9 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_tls_common.h +++ b/components/wpa_supplicant/src/eap_peer/eap_tls_common.h @@ -78,6 +78,11 @@ struct eap_ssl_data { * client_cert_conf: Whether client certificate has been configured */ bool client_cert_conf; + + /** + * tls_v13 - Whether TLS v1.3 or newer is used + */ + int tls_v13; }; From 6a83540ae09b2fa56bd5d439938e77e8a685d00c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 1 May 2018 17:49:19 +0300 Subject: [PATCH 04/35] EAP-TLS peer: Support fragmentation of last message With TLS v1.3, the Finished message from the client can require fragmentation. Postpone key derivation and marking of the EAP session fully completed until all the fragments of that last message are sent to avoid losing all the subsequent fragments. Signed-off-by: Jouni Malinen --- components/wpa_supplicant/src/eap_peer/eap_tls.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/components/wpa_supplicant/src/eap_peer/eap_tls.c b/components/wpa_supplicant/src/eap_peer/eap_tls.c index 3f7e89e260..b1fb8b6c54 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_tls.c +++ b/components/wpa_supplicant/src/eap_peer/eap_tls.c @@ -114,6 +114,11 @@ static void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data, { wpa_printf(MSG_DEBUG, "EAP-TLS: Done"); + if (data->ssl.tls_out) { + wpa_printf(MSG_DEBUG, "EAP-TLS: Fragment(s) remaining"); + return; + } + ret->methodState = METHOD_DONE; ret->decision = DECISION_UNCOND_SUCC; From 34a8628d4ef2a3a460a2714f275e091c9b5f0f49 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 1 May 2018 17:51:34 +0300 Subject: [PATCH 05/35] EAP-TLS peer: Allow NewSessionTicket after Client Finished with TLS v1.3 The EAP session cannot be marked fully completed on sending Client Finished with TLS v1.3 since the server may still send NewSessionTicket before EAP-Success. Signed-off-by: Jouni Malinen --- components/wpa_supplicant/src/eap_peer/eap_tls.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/components/wpa_supplicant/src/eap_peer/eap_tls.c b/components/wpa_supplicant/src/eap_peer/eap_tls.c index b1fb8b6c54..c31768cf32 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_tls.c +++ b/components/wpa_supplicant/src/eap_peer/eap_tls.c @@ -119,8 +119,15 @@ static void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data, return; } - ret->methodState = METHOD_DONE; - ret->decision = DECISION_UNCOND_SUCC; + if (data->ssl.tls_v13) { + /* A possible NewSessionTicket may be received before + * EAP-Success, so need to allow it to be received. */ + ret->methodState = METHOD_MAY_CONT; + ret->decision = DECISION_COND_SUCC; + } else { + ret->methodState = METHOD_DONE; + ret->decision = DECISION_UNCOND_SUCC; + } os_free(data->key_data); data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, From e9f6949d7e6bc84e492df921c7dca5f01aee6b00 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 1 May 2018 17:53:07 +0300 Subject: [PATCH 06/35] EAP-TLS peer: MSK/EMSK derivation with TLS v1.3 Use new MSK/EMSK derivation mechanism if TLS v1.3 or newer is used per draft-mattsson-eap-tls13-02.txt. Signed-off-by: Jouni Malinen --- components/wpa_supplicant/src/eap_peer/eap_tls.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/components/wpa_supplicant/src/eap_peer/eap_tls.c b/components/wpa_supplicant/src/eap_peer/eap_tls.c index c31768cf32..d657beab03 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_tls.c +++ b/components/wpa_supplicant/src/eap_peer/eap_tls.c @@ -112,6 +112,8 @@ static struct wpabuf * eap_tls_failure(struct eap_sm *sm, static void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data, struct eap_method_ret *ret) { + const char *label; + wpa_printf(MSG_DEBUG, "EAP-TLS: Done"); if (data->ssl.tls_out) { @@ -120,18 +122,21 @@ static void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data, } if (data->ssl.tls_v13) { + label = "client EAP encryption KM"; + /* A possible NewSessionTicket may be received before * EAP-Success, so need to allow it to be received. */ ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_COND_SUCC; } else { + label = "client EAP encryption"; + ret->methodState = METHOD_DONE; ret->decision = DECISION_UNCOND_SUCC; } os_free(data->key_data); - data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, - "client EAP encryption", + data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, label, EAP_TLS_KEY_LEN + EAP_EMSK_LEN); if (data->key_data) { From a2336b74f9c2b9881b09b193c3689df256bf82b7 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 1 Jun 2018 17:41:59 +0300 Subject: [PATCH 07/35] EAP-TLS: Update key derivation label per draft-ietf-emu-eap-tls13-00 The label strings used for deriving Key_Material with TLS v1.3 were changed, so update the implementation to match the new values. Signed-off-by: Jouni Malinen --- components/wpa_supplicant/src/eap_peer/eap_tls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/wpa_supplicant/src/eap_peer/eap_tls.c b/components/wpa_supplicant/src/eap_peer/eap_tls.c index d657beab03..a4da54c606 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_tls.c +++ b/components/wpa_supplicant/src/eap_peer/eap_tls.c @@ -122,7 +122,7 @@ static void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data, } if (data->ssl.tls_v13) { - label = "client EAP encryption KM"; + label = "EXPORTER_EAP_TLS_Key_Material"; /* A possible NewSessionTicket may be received before * EAP-Success, so need to allow it to be received. */ From ed8452d53ff12647e21dd03e5a2ba24628f09c3b Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 1 Jun 2018 17:58:56 +0300 Subject: [PATCH 08/35] EAP-TLS: Derive Session-Id using TLS-Exporter when TLS v1.3 is used This updates Session-Id derivation with TLS v1.3 per draft-ietf-emu-eap-tls13-00. Signed-off-by: Jouni Malinen --- components/wpa_supplicant/src/eap_peer/eap_tls_common.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/components/wpa_supplicant/src/eap_peer/eap_tls_common.c b/components/wpa_supplicant/src/eap_peer/eap_tls_common.c index 60ef6096bd..f78921d32e 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_tls_common.c +++ b/components/wpa_supplicant/src/eap_peer/eap_tls_common.c @@ -303,6 +303,13 @@ u8 * eap_peer_tls_derive_session_id(struct eap_sm *sm, struct tls_random keys; u8 *out; + if (eap_type == EAP_TYPE_TLS && data->tls_v13) { + *len = 64; + return eap_peer_tls_derive_key(sm, data, + "EXPORTER_EAP_TLS_Session-Id", + 64); + } + /* * TLS library did not support session ID generation, * so get the needed TLS session parameters From bb16734aa90a5129d087c7a5ad50ffab6dddd065 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 5 Jan 2019 18:00:26 +0200 Subject: [PATCH 09/35] EAP-TLS: Update Session-Id derivation with TLS v1.3 Move to the version used in draft-ietf-emu-eap-tls13-03.txt, i.e., include the 0x0D prefix and use a different TLS-Exporter() label string. Signed-off-by: Jouni Malinen --- .../src/eap_peer/eap_tls_common.c | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/components/wpa_supplicant/src/eap_peer/eap_tls_common.c b/components/wpa_supplicant/src/eap_peer/eap_tls_common.c index f78921d32e..ea1ad72571 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_tls_common.c +++ b/components/wpa_supplicant/src/eap_peer/eap_tls_common.c @@ -304,10 +304,26 @@ u8 * eap_peer_tls_derive_session_id(struct eap_sm *sm, u8 *out; if (eap_type == EAP_TYPE_TLS && data->tls_v13) { - *len = 64; - return eap_peer_tls_derive_key(sm, data, - "EXPORTER_EAP_TLS_Session-Id", - 64); + u8 *id, *method_id; + + /* Session-Id = || Method-Id + * Method-Id = TLS-Exporter("EXPORTER_EAP_TLS_Method-Id", + * "", 64) + */ + *len = 1 + 64; + id = os_malloc(*len); + if (!id) + return NULL; + method_id = eap_peer_tls_derive_key( + sm, data, "EXPORTER_EAP_TLS_Method-Id", 64); + if (!method_id) { + os_free(id); + return NULL; + } + id[0] = eap_type; + os_memcpy(id + 1, method_id, 64); + os_free(method_id); + return id; } /* From f4d7329ae661aed22cb72dd5d00fdd57b31ae26b Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 29 Jun 2014 21:16:30 +0300 Subject: [PATCH 10/35] 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)) { From aa987d418ec2c24c584d97e607ac2d073379c5d3 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 1 Feb 2019 23:52:28 +0200 Subject: [PATCH 11/35] EAP-PEAP: Derive EMSK and use 128-octet derivation for MSK Derive EMSK when using EAP-PEAP to enable ERP. In addition, change the MSK derivation for EAP-PEAP to always derive 128 octets of key material instead of the 64 octets to cover just the MSK. This is needed with the PRF used in TLS 1.3 since the output length is mixed into the PRF context. Signed-off-by: Jouni Malinen --- .../wpa_supplicant/src/eap_peer/eap_peap.c | 36 +++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/components/wpa_supplicant/src/eap_peer/eap_peap.c b/components/wpa_supplicant/src/eap_peer/eap_peap.c index 3fe6ab1b8d..1e6f94f14c 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_peap.c +++ b/components/wpa_supplicant/src/eap_peer/eap_peap.c @@ -1,6 +1,6 @@ /* * EAP peer method: EAP-PEAP (draft-josefsson-pppext-eap-tls-eap-10.txt) - * Copyright (c) 2004-2015, Jouni Malinen + * Copyright (c) 2004-2019, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -74,7 +74,7 @@ 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); + bin_clear_free(data->key_data, EAP_TLS_KEY_LEN + EAP_EMSK_LEN); data->key_data = NULL; } } @@ -1203,12 +1203,18 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv, "key derivation", label); data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, label, - EAP_TLS_KEY_LEN); + EAP_TLS_KEY_LEN + + EAP_EMSK_LEN); if (data->key_data) { wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Derived key", data->key_data, EAP_TLS_KEY_LEN); + wpa_hexdump_key(MSG_DEBUG, + "EAP-PEAP: Derived EMSK", + data->key_data + + EAP_TLS_KEY_LEN, + EAP_EMSK_LEN); } else { wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to " "derive key"); @@ -1391,6 +1397,29 @@ eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len) } +static u8 * eap_peap_get_emsk(struct eap_sm *sm, void *priv, size_t *len) +{ + struct eap_peap_data *data = priv; + u8 *key; + + if (!data->key_data || !data->phase2_success) + return NULL; + + if (data->crypto_binding_used) { + /* [MS-PEAP] does not define EMSK derivation */ + return NULL; + } + + key = os_memdup(data->key_data + EAP_TLS_KEY_LEN, EAP_EMSK_LEN); + if (!key) + return NULL; + + *len = EAP_EMSK_LEN; + + return key; +} + + static u8 * eap_peap_get_session_id(struct eap_sm *sm, void *priv, size_t *len) { @@ -1427,6 +1456,7 @@ eap_peer_peap_register(void) eap->process = eap_peap_process; eap->isKeyAvailable = eap_peap_isKeyAvailable; eap->getKey = eap_peap_getKey; + eap->get_emsk = eap_peap_get_emsk; eap->get_status = eap_peap_get_status; eap->has_reauth_data = eap_peap_has_reauth_data; eap->deinit_for_reauth = eap_peap_deinit_for_reauth; From 1e38fa2c129108e37990cabbadfdf8e958efa67a Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 5 Feb 2019 20:26:50 +0200 Subject: [PATCH 12/35] EAP peer: Clear temporary message buffers before freeing These buffers in TLS-based EAP methods might contain keys or password (e.g., when using TTLS-PAP or PEAP-GTC), so clear them explicitly to avoid leaving such material into heap memory unnecessarily. Signed-off-by: Jouni Malinen --- .../wpa_supplicant/src/eap_peer/eap_fast.c | 26 +++++------ .../wpa_supplicant/src/eap_peer/eap_peap.c | 40 +++++++++-------- .../wpa_supplicant/src/eap_peer/eap_ttls.c | 43 ++++++++++--------- 3 files changed, 56 insertions(+), 53 deletions(-) diff --git a/components/wpa_supplicant/src/eap_peer/eap_fast.c b/components/wpa_supplicant/src/eap_peer/eap_fast.c index 37e0ef18b7..2031c53933 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_fast.c +++ b/components/wpa_supplicant/src/eap_peer/eap_fast.c @@ -249,8 +249,8 @@ static void eap_fast_deinit(struct eap_sm *sm, void *priv) 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); - wpabuf_free(data->pending_resp); + wpabuf_clear_free(data->pending_phase2_req); + wpabuf_clear_free(data->pending_resp); os_free(data); } @@ -800,7 +800,7 @@ static struct wpabuf * eap_fast_process_crypto_binding( ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; data->phase2_success = 0; - wpabuf_free(resp); + wpabuf_clear_free(resp); return NULL; } @@ -814,7 +814,7 @@ static struct wpabuf * eap_fast_process_crypto_binding( } else { wpa_printf(MSG_ERROR, "EAP-FAST: Failed to derive " "Session-Id"); - wpabuf_free(resp); + wpabuf_clear_free(resp); return NULL; } } @@ -1135,7 +1135,7 @@ static int eap_fast_encrypt_response(struct eap_sm *sm, wpa_printf(MSG_INFO, "EAP-FAST: Failed to encrypt a Phase 2 " "frame"); } - wpabuf_free(resp); + wpabuf_clear_free(resp); return 0; } @@ -1313,14 +1313,14 @@ continue_req: wpa_printf(MSG_INFO, "EAP-FAST: Too short Phase 2 " "TLV frame (len=%lu)", (unsigned long) wpabuf_len(in_decrypted)); - wpabuf_free(in_decrypted); + wpabuf_clear_free(in_decrypted); return -1; } res = eap_fast_process_decrypted(sm, data, ret, identifier, in_decrypted, out_data); - wpabuf_free(in_decrypted); + wpabuf_clear_free(in_decrypted); return res; } @@ -1598,7 +1598,7 @@ static struct wpabuf * eap_fast_process(struct eap_sm *sm, void *priv, if (sm->waiting_ext_cert_check) { wpa_printf(MSG_DEBUG, "EAP-FAST: Waiting external server certificate validation"); - wpabuf_free(data->pending_resp); + wpabuf_clear_free(data->pending_resp); data->pending_resp = resp; return NULL; } @@ -1627,7 +1627,7 @@ static struct wpabuf * eap_fast_process(struct eap_sm *sm, void *priv, "EAP-FAST: Could not derive keys"); ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; - wpabuf_free(resp); + wpabuf_clear_free(resp); return NULL; } } @@ -1636,7 +1636,7 @@ static struct wpabuf * eap_fast_process(struct eap_sm *sm, void *priv, /* * Application data included in the handshake message. */ - wpabuf_free(data->pending_phase2_req); + wpabuf_clear_free(data->pending_phase2_req); data->pending_phase2_req = resp; resp = NULL; res = eap_fast_decrypt(sm, data, ret, id, &msg, &resp); @@ -1644,7 +1644,7 @@ static struct wpabuf * eap_fast_process(struct eap_sm *sm, void *priv, } if (res == 1) { - wpabuf_free(resp); + wpabuf_clear_free(resp); return eap_peer_tls_build_ack(id, EAP_TYPE_FAST, data->fast_version); } @@ -1670,9 +1670,9 @@ static void eap_fast_deinit_for_reauth(struct eap_sm *sm, void *priv) data->phase2_method->deinit_for_reauth(sm, data->phase2_priv); os_free(data->key_block_p); data->key_block_p = NULL; - wpabuf_free(data->pending_phase2_req); + wpabuf_clear_free(data->pending_phase2_req); data->pending_phase2_req = NULL; - wpabuf_free(data->pending_resp); + wpabuf_clear_free(data->pending_resp); data->pending_resp = NULL; } diff --git a/components/wpa_supplicant/src/eap_peer/eap_peap.c b/components/wpa_supplicant/src/eap_peer/eap_peap.c index 1e6f94f14c..0c52ad92a3 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_peap.c +++ b/components/wpa_supplicant/src/eap_peer/eap_peap.c @@ -209,9 +209,9 @@ eap_peap_deinit(struct eap_sm *sm, void *priv) eap_peer_tls_ssl_deinit(sm, &data->ssl); eap_peap_free_key(data); os_free(data->session_id); - wpabuf_free(data->pending_phase2_req); - wpabuf_free(data->pending_resp); - os_free(data); + wpabuf_clear_free(data->pending_phase2_req); + wpabuf_clear_free(data->pending_resp); + bin_clear_free(data, sizeof(*data)); } @@ -406,7 +406,7 @@ eap_tlv_build_result(struct eap_sm *sm, wpabuf_put_be16(msg, status); /* Status */ if (crypto_tlv_used && eap_tlv_add_cryptobinding(sm, data, msg)) { - wpabuf_free(msg); + wpabuf_clear_free(msg); return NULL; } @@ -721,10 +721,11 @@ static int eap_peap_phase2_request(struct eap_sm *sm, if (*resp == NULL) { ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; + wpabuf_clear_free(buf); return -1; } wpabuf_put_buf(*resp, buf); - wpabuf_free(buf); + wpabuf_clear_free(buf); break; } } @@ -795,7 +796,7 @@ static int eap_peap_phase2_request(struct eap_sm *sm, if (*resp == NULL) { wpa_printf(MSG_ERROR, "phase 2 response failure"); - wpabuf_free(data->pending_phase2_req); + wpabuf_clear_free(data->pending_phase2_req); data->pending_phase2_req = wpabuf_alloc_copy(hdr, len); } /* @@ -883,7 +884,7 @@ continue_req: struct wpabuf *nmsg = wpabuf_alloc(sizeof(struct eap_hdr) + wpabuf_len(in_decrypted)); if (nmsg == NULL) { - wpabuf_free(in_decrypted); + wpabuf_clear_free(in_decrypted); return 0; } nhdr = wpabuf_put(nmsg, sizeof(*nhdr)); @@ -893,7 +894,7 @@ continue_req: nhdr->length = host_to_be16(sizeof(struct eap_hdr) + wpabuf_len(in_decrypted)); - wpabuf_free(in_decrypted); + wpabuf_clear_free(in_decrypted); in_decrypted = nmsg; } @@ -945,7 +946,7 @@ continue_req: wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 " "EAP frame (len=%lu)", (unsigned long) wpabuf_len(in_decrypted)); - wpabuf_free(in_decrypted); + wpabuf_clear_free(in_decrypted); return 0; } len = be_to_host16(hdr->length); @@ -954,7 +955,7 @@ continue_req: "Phase 2 EAP frame (len=%lu hdr->length=%lu)", (unsigned long) wpabuf_len(in_decrypted), (unsigned long) len); - wpabuf_free(in_decrypted); + wpabuf_clear_free(in_decrypted); return 0; } if (len < wpabuf_len(in_decrypted)) { @@ -971,7 +972,7 @@ continue_req: case EAP_CODE_REQUEST: if (eap_peap_phase2_request(sm, data, ret, in_decrypted, &resp)) { - wpabuf_free(in_decrypted); + wpabuf_clear_free(in_decrypted); wpa_printf(MSG_ERROR, "EAP-PEAP: Phase2 Request " "processing failed"); return 0; @@ -990,7 +991,7 @@ continue_req: "completed successfully"); ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; - wpabuf_free(in_decrypted); + wpabuf_clear_free(in_decrypted); return 0; } wpa_printf(MSG_DEBUG, "EAP-PEAP: Version 1 - " @@ -1000,7 +1001,7 @@ continue_req: ret->methodState = METHOD_DONE; data->phase2_success = 1; if (data->peap_outer_success == 2) { - wpabuf_free(in_decrypted); + wpabuf_clear_free(in_decrypted); wpa_printf(MSG_DEBUG, "EAP-PEAP: Use TLS ACK " "to finish authentication"); return 1; @@ -1046,7 +1047,7 @@ continue_req: break; } - wpabuf_free(in_decrypted); + wpabuf_clear_free(in_decrypted); if (resp) { int skip_change2 = 0; @@ -1078,7 +1079,7 @@ continue_req: wpa_printf(MSG_INFO, "EAP-PEAP: Failed to encrypt " "a Phase 2 frame"); } - wpabuf_free(resp); + wpabuf_clear_free(resp); } return 0; @@ -1178,7 +1179,7 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv, if (sm->waiting_ext_cert_check) { wpa_printf(MSG_DEBUG, "EAP-PEAP: Waiting external server certificate validation"); - wpabuf_free(data->pending_resp); + wpabuf_clear_free(data->pending_resp); data->pending_resp = resp; return NULL; } @@ -1261,6 +1262,7 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv, * Application data included in the handshake message. */ wpabuf_free(data->pending_phase2_req); + wpabuf_clear_free(data->pending_phase2_req); data->pending_phase2_req = resp; resp = NULL; wpabuf_set(&msg, pos, left); @@ -1274,7 +1276,7 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv, } if (res == 1) { - wpabuf_free(resp); + wpabuf_clear_free(resp); return eap_peer_tls_build_ack(id, EAP_TYPE_PEAP, data->peap_version); } @@ -1297,9 +1299,9 @@ static void eap_peap_deinit_for_reauth(struct eap_sm *sm, void *priv) { struct eap_peap_data *data = priv; - wpabuf_free(data->pending_phase2_req); + wpabuf_clear_free(data->pending_phase2_req); data->pending_phase2_req = NULL; - wpabuf_free(data->pending_resp); + wpabuf_clear_free(data->pending_resp); data->pending_resp = NULL; data->crypto_binding_used = 0; } diff --git a/components/wpa_supplicant/src/eap_peer/eap_ttls.c b/components/wpa_supplicant/src/eap_peer/eap_ttls.c index a78fece8ee..527cea5c74 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_ttls.c +++ b/components/wpa_supplicant/src/eap_peer/eap_ttls.c @@ -146,8 +146,8 @@ static void eap_ttls_deinit(struct eap_sm *sm, void *priv) eap_peer_tls_ssl_deinit(sm, &data->ssl); eap_ttls_free_key(data); os_free(data->session_id); - wpabuf_free(data->pending_phase2_req); - wpabuf_free(data->pending_resp); + wpabuf_clear_free(data->pending_phase2_req); + wpabuf_clear_free(data->pending_resp); os_free(data); } @@ -197,7 +197,7 @@ static int eap_ttls_avp_encapsulate(struct wpabuf **resp, u32 avp_code, msg = wpabuf_alloc(sizeof(struct ttls_avp) + wpabuf_len(*resp) + 4); if (msg == NULL) { - wpabuf_free(*resp); + wpabuf_clear_free(*resp); *resp = NULL; return -1; } @@ -207,7 +207,7 @@ static int eap_ttls_avp_encapsulate(struct wpabuf **resp, u32 avp_code, os_memcpy(pos, wpabuf_head(*resp), wpabuf_len(*resp)); pos += wpabuf_len(*resp); AVP_PAD(avp, pos); - wpabuf_free(*resp); + wpabuf_clear_free(*resp); wpabuf_put(msg, pos - avp); *resp = msg; return 0; @@ -457,7 +457,7 @@ static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm, challenge = eap_ttls_implicit_challenge( sm, data, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 1); if (challenge == NULL) { - wpabuf_free(msg); + wpabuf_clear_free(msg); wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to derive " "implicit challenge"); return -1; @@ -476,7 +476,7 @@ static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm, *pos++ = 0; /* Flags */ if (os_get_random(pos, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN) < 0) { os_free(challenge); - wpabuf_free(msg); + wpabuf_clear_free(msg); wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to get " "random data for peer challenge"); return -1; @@ -490,7 +490,7 @@ static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm, peer_challenge, pos, data->auth_response, data->master_key)) { os_free(challenge); - wpabuf_free(msg); + wpabuf_clear_free(msg); wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to derive " "response"); return -1; @@ -562,7 +562,7 @@ static int eap_ttls_phase2_request_mschap(struct eap_sm *sm, challenge = eap_ttls_implicit_challenge( sm, data, EAP_TTLS_MSCHAP_CHALLENGE_LEN + 1); if (challenge == NULL) { - wpabuf_free(msg); + wpabuf_clear_free(msg); wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAP: Failed to derive " "implicit challenge"); return -1; @@ -586,7 +586,7 @@ static int eap_ttls_phase2_request_mschap(struct eap_sm *sm, if (challenge_response(challenge, password, pos)) { wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAP: Failed derive password hash"); - wpabuf_free(msg); + wpabuf_clear_free(msg); return -1; } @@ -598,7 +598,7 @@ static int eap_ttls_phase2_request_mschap(struct eap_sm *sm, pos)) { wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAP: Failed derive password"); - wpabuf_free(msg); + wpabuf_clear_free(msg); return -1; } @@ -716,7 +716,7 @@ static int eap_ttls_phase2_request_chap(struct eap_sm *sm, challenge = eap_ttls_implicit_challenge( sm, data, EAP_TTLS_CHAP_CHALLENGE_LEN + 1); if (challenge == NULL) { - wpabuf_free(msg); + wpabuf_clear_free(msg); wpa_printf(MSG_ERROR, "EAP-TTLS/CHAP: Failed to derive " "implicit challenge"); return -1; @@ -1024,9 +1024,10 @@ static int eap_ttls_encrypt_response(struct eap_sm *sm, data->ttls_version, identifier, resp, out_data)) { wpa_printf(MSG_ERROR, "EAP-TTLS: Failed to encrypt a Phase 2 frame"); + wpabuf_clear_free(resp); return -1; } - wpabuf_free(resp); + wpabuf_clear_free(resp); return 0; } @@ -1246,7 +1247,7 @@ static int eap_ttls_process_decrypted(struct eap_sm *sm, config->pending_req_password || config->pending_req_otp || config->pending_req_new_password) { - wpabuf_free(data->pending_phase2_req); + wpabuf_clear_free(data->pending_phase2_req); data->pending_phase2_req = wpabuf_dup(in_decrypted); } @@ -1288,7 +1289,7 @@ static int eap_ttls_implicit_identity_request(struct eap_sm *sm, * processing when EAP request is re-processed after * user input. */ - wpabuf_free(data->pending_phase2_req); + wpabuf_clear_free(data->pending_phase2_req); data->pending_phase2_req = wpabuf_alloc(0); } @@ -1361,7 +1362,7 @@ static int eap_ttls_decrypt(struct eap_sm *sm, struct eap_ttls_data *data, in_decrypted = data->pending_phase2_req; data->pending_phase2_req = NULL; if (wpabuf_len(in_decrypted) == 0) { - wpabuf_free(in_decrypted); + wpabuf_clear_free(in_decrypted); return eap_ttls_implicit_identity_request( sm, data, ret, identifier, out_data); } @@ -1397,7 +1398,7 @@ continue_req: &parse, in_decrypted, out_data); done: - wpabuf_free(in_decrypted); + wpabuf_clear_free(in_decrypted); os_free(parse.eapdata); if (retval < 0) { @@ -1458,7 +1459,7 @@ static int eap_ttls_process_handshake(struct eap_sm *sm, if (sm->waiting_ext_cert_check) { wpa_printf(MSG_DEBUG, "EAP-TTLS: Waiting external server certificate validation"); - wpabuf_free(data->pending_resp); + wpabuf_clear_free(data->pending_resp); data->pending_resp = *out_data; *out_data = NULL; return 0; @@ -1493,7 +1494,7 @@ static int eap_ttls_process_handshake(struct eap_sm *sm, /* * Application data included in the handshake message. */ - wpabuf_free(data->pending_phase2_req); + wpabuf_clear_free(data->pending_phase2_req); data->pending_phase2_req = *out_data; *out_data = NULL; wpabuf_set(&msg, in_data, in_len); @@ -1582,7 +1583,7 @@ static struct wpabuf * eap_ttls_process(struct eap_sm *sm, void *priv, /* FIX: what about res == -1? Could just move all error processing into * the other functions and get rid of this res==1 case here. */ if (res == 1) { - wpabuf_free(resp); + wpabuf_clear_free(resp); return eap_peer_tls_build_ack(id, EAP_TYPE_TTLS, data->ttls_version); } @@ -1602,9 +1603,9 @@ static bool eap_ttls_has_reauth_data(struct eap_sm *sm, void *priv) static void eap_ttls_deinit_for_reauth(struct eap_sm *sm, void *priv) { struct eap_ttls_data *data = priv; - wpabuf_free(data->pending_phase2_req); + wpabuf_clear_free(data->pending_phase2_req); data->pending_phase2_req = NULL; - wpabuf_free(data->pending_resp); + wpabuf_clear_free(data->pending_resp); data->pending_resp = NULL; #ifdef EAP_TNC data->ready_for_tnc = 0; From 562bc59576ddaa1adfaa89e16ef5667ac4785715 Mon Sep 17 00:00:00 2001 From: Ervin Oro Date: Mon, 11 Mar 2019 13:21:36 +0200 Subject: [PATCH 13/35] Add support for an optional context parameter to TLS exporter Allow an additional context value to be passed to TLS exporter as specified in RFC 5705 section 4. This does not yet implement it for the internal TLS implementation. However, as currently nothing uses context yet, this will not break anything right now. WolfSSL maintainers also stated that they are not going to add context support yet, but would look into it if/when this is required by a published draft or a standard. Signed-off-by: Ervin Oro --- .../esp_supplicant/src/crypto/tls_mbedtls.c | 9 +++++++-- components/wpa_supplicant/src/eap_peer/eap_peap.c | 1 + components/wpa_supplicant/src/eap_peer/eap_tls.c | 1 + .../wpa_supplicant/src/eap_peer/eap_tls_common.c | 13 +++++++++---- .../wpa_supplicant/src/eap_peer/eap_tls_common.h | 3 ++- components/wpa_supplicant/src/eap_peer/eap_ttls.c | 4 +++- 6 files changed, 23 insertions(+), 8 deletions(-) diff --git a/components/wpa_supplicant/esp_supplicant/src/crypto/tls_mbedtls.c b/components/wpa_supplicant/esp_supplicant/src/crypto/tls_mbedtls.c index 42b846a802..274ed6af70 100644 --- a/components/wpa_supplicant/esp_supplicant/src/crypto/tls_mbedtls.c +++ b/components/wpa_supplicant/esp_supplicant/src/crypto/tls_mbedtls.c @@ -997,9 +997,13 @@ int tls_connection_set_session_ticket_cb(void *tls_ctx, } static int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, - const char *label, int server_random_first, + const char *label, const u8 *context, + size_t context_len, int server_random_first, u8 *out, size_t out_len) { + if (context) + return -1; + int ret; u8 seed[2 * TLS_RANDOM_LEN]; mbedtls_ssl_context *ssl = &conn->tls->ssl; @@ -1038,7 +1042,8 @@ int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn, const char *label, const u8 *context, size_t context_len, u8 *out, size_t out_len) { - return tls_connection_prf(tls_ctx, conn, label, 0, out, out_len); + return tls_connection_prf(tls_ctx, conn, label,context, context_len, + 0, out, out_len); } int tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn, diff --git a/components/wpa_supplicant/src/eap_peer/eap_peap.c b/components/wpa_supplicant/src/eap_peer/eap_peap.c index 0c52ad92a3..a4cf1a2376 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_peap.c +++ b/components/wpa_supplicant/src/eap_peer/eap_peap.c @@ -1204,6 +1204,7 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv, "key derivation", label); data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, label, + NULL, 0, EAP_TLS_KEY_LEN + EAP_EMSK_LEN); if (data->key_data) { diff --git a/components/wpa_supplicant/src/eap_peer/eap_tls.c b/components/wpa_supplicant/src/eap_peer/eap_tls.c index ec16b1eb68..6e219fbf31 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_tls.c +++ b/components/wpa_supplicant/src/eap_peer/eap_tls.c @@ -146,6 +146,7 @@ static void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data, eap_tls_free_key(data); data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, label, + NULL, 0, EAP_TLS_KEY_LEN + EAP_EMSK_LEN); if (data->key_data) { diff --git a/components/wpa_supplicant/src/eap_peer/eap_tls_common.c b/components/wpa_supplicant/src/eap_peer/eap_tls_common.c index ea1ad72571..8fe3a3a033 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_tls_common.c +++ b/components/wpa_supplicant/src/eap_peer/eap_tls_common.c @@ -256,6 +256,8 @@ void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data) * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() * @data: Data for TLS processing * @label: Label string for deriving the keys, e.g., "client EAP encryption" + * @context: Optional extra upper-layer context (max len 2^16) + * @context_len: The length of the context value * @len: Length of the key material to generate (usually 64 for MSK) * Returns: Pointer to allocated key on success or %NULL on failure * @@ -264,9 +266,12 @@ void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data) * different label to bind the key usage into the generated material. * * The caller is responsible for freeing the returned buffer. + * + * Note: To provide the RFC 5705 context, the context variable must be non-NULL. */ u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data, - const char *label, size_t len) + const char *label, const u8 *context, + size_t context_len, size_t len) { u8 *out; @@ -274,8 +279,8 @@ u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data, if (out == NULL) return NULL; - if (tls_connection_export_key(data->ssl_ctx, data->conn, label, 0, 0, out, - len)) { + if (tls_connection_export_key(data->ssl_ctx, data->conn, label, + context, context_len, out, len)) { os_free(out); return NULL; } @@ -315,7 +320,7 @@ u8 * eap_peer_tls_derive_session_id(struct eap_sm *sm, if (!id) return NULL; method_id = eap_peer_tls_derive_key( - sm, data, "EXPORTER_EAP_TLS_Method-Id", 64); + sm, data, "EXPORTER_EAP_TLS_Method-Id", NULL, 0, 64); if (!method_id) { os_free(id); return NULL; diff --git a/components/wpa_supplicant/src/eap_peer/eap_tls_common.h b/components/wpa_supplicant/src/eap_peer/eap_tls_common.h index fea1458ee9..de91692c7a 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_tls_common.h +++ b/components/wpa_supplicant/src/eap_peer/eap_tls_common.h @@ -103,7 +103,8 @@ int eap_peer_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data, struct eap_peer_config *config, u8 eap_type); void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data); u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data, - const char *label, size_t len); + const char *label, const u8 *context, + size_t context_len, size_t len); u8 * eap_peer_tls_derive_session_id(struct eap_sm *sm, struct eap_ssl_data *data, u8 eap_type, size_t *len); diff --git a/components/wpa_supplicant/src/eap_peer/eap_ttls.c b/components/wpa_supplicant/src/eap_peer/eap_ttls.c index 527cea5c74..0005c427c7 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_ttls.c +++ b/components/wpa_supplicant/src/eap_peer/eap_ttls.c @@ -220,6 +220,7 @@ static int eap_ttls_v0_derive_key(struct eap_sm *sm, eap_ttls_free_key(data); data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, "ttls keying material", + NULL, 0, EAP_TLS_KEY_LEN); if (!data->key_data) { wpa_printf(MSG_ERROR, "EAP-TTLS: Failed to derive key"); @@ -251,7 +252,8 @@ static int eap_ttls_v0_derive_key(struct eap_sm *sm, static u8 * eap_ttls_implicit_challenge(struct eap_sm *sm, struct eap_ttls_data *data, size_t len) { - return eap_peer_tls_derive_key(sm, &data->ssl, "ttls challenge", len); + return eap_peer_tls_derive_key(sm, &data->ssl, "ttls challenge", + NULL, 0, len); } #endif /* CONFIG_FIPS */ From 886bf9e82f4b21ce62371be9370cd9a67cec8107 Mon Sep 17 00:00:00 2001 From: Sarvesh Bodakhe Date: Wed, 5 Jul 2023 11:17:29 +0530 Subject: [PATCH 14/35] feat(wpa_supplicant): Add support for RFC 5705 TLS exporter context with mbedTLS --- .../esp_supplicant/src/crypto/tls_mbedtls.c | 28 ++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/components/wpa_supplicant/esp_supplicant/src/crypto/tls_mbedtls.c b/components/wpa_supplicant/esp_supplicant/src/crypto/tls_mbedtls.c index 274ed6af70..606af1a0e3 100644 --- a/components/wpa_supplicant/esp_supplicant/src/crypto/tls_mbedtls.c +++ b/components/wpa_supplicant/esp_supplicant/src/crypto/tls_mbedtls.c @@ -1001,19 +1001,30 @@ static int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, size_t context_len, int server_random_first, u8 *out, size_t out_len) { - if (context) + int ret; + u8 *seed, *pos; + size_t seed_len = 2 * TLS_RANDOM_LEN; + mbedtls_ssl_context *ssl = &conn->tls->ssl; + + if (context_len > 65535) return -1; - int ret; - u8 seed[2 * TLS_RANDOM_LEN]; - mbedtls_ssl_context *ssl = &conn->tls->ssl; + if (context) + seed_len += 2 + context_len; + + seed = os_malloc(seed_len); + if (!seed) { + return -1; + } if (!ssl) { wpa_printf(MSG_ERROR, "TLS: %s, session ingo is null", __func__); + os_free(seed); return -1; } if (!mbedtls_ssl_is_handshake_over(ssl)) { wpa_printf(MSG_ERROR, "TLS: %s, incorrect tls state=%d", __func__, ssl->MBEDTLS_PRIVATE(state)); + os_free(seed); return -1; } @@ -1024,14 +1035,23 @@ static int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, os_memcpy(seed, conn->randbytes, 2 * TLS_RANDOM_LEN); } + if (context) { + pos = seed + 2 * TLS_RANDOM_LEN; + WPA_PUT_BE16(pos, context_len); + pos += 2; + os_memcpy(pos, context, context_len); + } + wpa_hexdump_key(MSG_MSGDUMP, "random", seed, 2 * TLS_RANDOM_LEN); wpa_hexdump_key(MSG_MSGDUMP, "master", ssl->MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(master), TLS_MASTER_SECRET_LEN); ret = mbedtls_ssl_tls_prf(conn->tls_prf_type, conn->master_secret, TLS_MASTER_SECRET_LEN, label, seed, 2 * TLS_RANDOM_LEN, out, out_len); + os_free(seed); if (ret < 0) { wpa_printf(MSG_ERROR, "prf failed, ret=%d", ret); + return -1; } wpa_hexdump_key(MSG_MSGDUMP, "key", out, out_len); From caf49e8c10b29561725e31b744c29affde0a8453 Mon Sep 17 00:00:00 2001 From: Ervin Oro Date: Mon, 15 Apr 2019 20:05:49 +0300 Subject: [PATCH 15/35] Add Type-Code context to EAP-TLS 1.3 exported Key_Material and Method-Id Change to require the Type-Code in context for Key_Material and Method-Id has now been published as draft-ietf-emu-eap-tls13-04. https://tools.ietf.org/html/draft-ietf-emu-eap-tls13-04#section-2.3 Signed-off-by: Ervin Oro --- components/wpa_supplicant/src/eap_peer/eap_tls.c | 7 ++++++- components/wpa_supplicant/src/eap_peer/eap_tls_common.c | 5 +++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/components/wpa_supplicant/src/eap_peer/eap_tls.c b/components/wpa_supplicant/src/eap_peer/eap_tls.c index 6e219fbf31..169b4e265d 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_tls.c +++ b/components/wpa_supplicant/src/eap_peer/eap_tls.c @@ -122,6 +122,9 @@ static void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data, struct eap_method_ret *ret) { const char *label; + const u8 eap_tls13_context[] = { EAP_TYPE_TLS }; + const u8 *context = NULL; + size_t context_len = 0; wpa_printf(MSG_DEBUG, "EAP-TLS: Done"); @@ -132,6 +135,8 @@ static void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data, if (data->ssl.tls_v13) { label = "EXPORTER_EAP_TLS_Key_Material"; + context = eap_tls13_context; + context_len = 1; /* A possible NewSessionTicket may be received before * EAP-Success, so need to allow it to be received. */ @@ -146,7 +151,7 @@ static void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data, eap_tls_free_key(data); data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, label, - NULL, 0, + context, context_len, EAP_TLS_KEY_LEN + EAP_EMSK_LEN); if (data->key_data) { diff --git a/components/wpa_supplicant/src/eap_peer/eap_tls_common.c b/components/wpa_supplicant/src/eap_peer/eap_tls_common.c index 8fe3a3a033..c3081f7b17 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_tls_common.c +++ b/components/wpa_supplicant/src/eap_peer/eap_tls_common.c @@ -310,17 +310,18 @@ u8 * eap_peer_tls_derive_session_id(struct eap_sm *sm, if (eap_type == EAP_TYPE_TLS && data->tls_v13) { u8 *id, *method_id; + const u8 context[] = { EAP_TYPE_TLS }; /* Session-Id = || Method-Id * Method-Id = TLS-Exporter("EXPORTER_EAP_TLS_Method-Id", - * "", 64) + * Type-Code, 64) */ *len = 1 + 64; id = os_malloc(*len); if (!id) return NULL; method_id = eap_peer_tls_derive_key( - sm, data, "EXPORTER_EAP_TLS_Method-Id", NULL, 0, 64); + sm, data, "EXPORTER_EAP_TLS_Method-Id", context, 1, 64); if (!method_id) { os_free(id); return NULL; From a9170c6a205ec7a6bd5c4a179ccf475f52f004f6 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 12 Jul 2019 23:38:05 +0300 Subject: [PATCH 16/35] EAP-TLS peer: Handle possible application data at the end EAP-TLS with TLS 1.3 uses an empty application data record from the server to indicate end of the exchange, so EAP-TLS peer will need to check for this special case and finish the exchange with an empty EAP-TLS (ACK) so that the server can send out EAP-Success. Signed-off-by: Jouni Malinen --- components/wpa_supplicant/src/eap_peer/eap_tls.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/components/wpa_supplicant/src/eap_peer/eap_tls.c b/components/wpa_supplicant/src/eap_peer/eap_tls.c index 169b4e265d..82e307d422 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_tls.c +++ b/components/wpa_supplicant/src/eap_peer/eap_tls.c @@ -242,6 +242,18 @@ static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv, return NULL; } + if (res == 2) { + /* Application data included in the handshake message (used by + * EAP-TLS 1.3 to indicate conclusion of the exchange). */ + wpa_hexdump_buf(MSG_DEBUG, "EAP-TLS: Received Application Data", + resp); + wpa_hexdump_buf(MSG_DEBUG, "EAP-TLS: Remaining tls_out data", + data->ssl.tls_out); + eap_peer_tls_reset_output(&data->ssl); + /* Send an ACK to allow the server to complete exchange */ + res = 1; + } + if (tls_connection_established(data->ssl_ctx, data->ssl.conn)) eap_tls_success(sm, data, ret); From a5b01a93ff19d3cb6ddc088cf6c5ab4d43dda8ea Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 17 Aug 2019 12:11:50 +0300 Subject: [PATCH 17/35] EAP-TTLS peer: Support vendor EAP method in Phase 2 The implementation was previously hardcoded to use only the non-expanded IETF EAP methods in Phase 2. Extend that to allow vendor EAP methods with expanded header to be used. Signed-off-by: Jouni Malinen --- .../wpa_supplicant/src/eap_peer/eap_ttls.c | 45 +++++++++++++------ 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/components/wpa_supplicant/src/eap_peer/eap_ttls.c b/components/wpa_supplicant/src/eap_peer/eap_ttls.c index 0005c427c7..40f65725d8 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_ttls.c +++ b/components/wpa_supplicant/src/eap_peer/eap_ttls.c @@ -259,11 +259,11 @@ static u8 * eap_ttls_implicit_challenge(struct eap_sm *sm, static void eap_ttls_phase2_select_eap_method(struct eap_ttls_data *data, - u8 method) + int vendor, enum eap_type method) { size_t i; for (i = 0; i < data->num_phase2_eap_types; i++) { - if (data->phase2_eap_types[i].vendor != EAP_VENDOR_IETF || + if (data->phase2_eap_types[i].vendor != vendor || data->phase2_eap_types[i].method != method) continue; @@ -310,17 +310,19 @@ static int eap_ttls_phase2_request_eap_method(struct eap_sm *sm, struct eap_ttls_data *data, struct eap_method_ret *ret, struct eap_hdr *hdr, size_t len, - u8 method, struct wpabuf **resp) + int vendor, enum eap_type method, + struct wpabuf **resp) { #ifdef EAP_TNC if (data->tnc_started && data->phase2_method && - data->phase2_priv && method == EAP_TYPE_TNC && + data->phase2_priv && + vendor == EAP_VENDOR_IETF && method == EAP_TYPE_TNC && data->phase2_eap_type.method == EAP_TYPE_TNC) return eap_ttls_phase2_eap_process(sm, data, ret, hdr, len, resp); if (data->ready_for_tnc && !data->tnc_started && - method == EAP_TYPE_TNC) { + vendor == EAP_VENDOR_IETF && method == EAP_TYPE_TNC) { wpa_printf(MSG_DEBUG, "EAP-TTLS: Start TNC after completed " "EAP method"); data->tnc_started = 1; @@ -334,7 +336,7 @@ static int eap_ttls_phase2_request_eap_method(struct eap_sm *sm, return -1; } - data->phase2_eap_type.vendor = EAP_VENDOR_IETF; + data->phase2_eap_type.vendor = vendor; data->phase2_eap_type.method = method; wpa_printf(MSG_DEBUG, "EAP-TTLS: Selected " "Phase 2 EAP vendor %d method %d (TNC)", @@ -348,10 +350,11 @@ static int eap_ttls_phase2_request_eap_method(struct eap_sm *sm, if (data->phase2_eap_type.vendor == EAP_VENDOR_IETF && data->phase2_eap_type.method == EAP_TYPE_NONE) - eap_ttls_phase2_select_eap_method(data, method); + eap_ttls_phase2_select_eap_method(data, vendor, method); - if (method != data->phase2_eap_type.method || method == EAP_TYPE_NONE) - { + if (vendor != data->phase2_eap_type.vendor || + method != data->phase2_eap_type.method || + (vendor == EAP_VENDOR_IETF && method == EAP_TYPE_NONE)) { if (eap_peer_tls_phase2_nak(data->phase2_eap_types, data->num_phase2_eap_types, hdr, resp)) @@ -360,8 +363,7 @@ static int eap_ttls_phase2_request_eap_method(struct eap_sm *sm, } if (data->phase2_priv == NULL) { - data->phase2_method = eap_peer_get_eap_method( - EAP_VENDOR_IETF, method); + data->phase2_method = eap_peer_get_eap_method(vendor, method); if (data->phase2_method) { sm->init_phase2 = 1; data->phase2_priv = data->phase2_method->init(sm); @@ -369,8 +371,9 @@ static int eap_ttls_phase2_request_eap_method(struct eap_sm *sm, } } if (data->phase2_priv == NULL || data->phase2_method == NULL) { - wpa_printf(MSG_INFO, "EAP-TTLS: failed to initialize " - "Phase 2 EAP method %d", method); + wpa_printf(MSG_INFO, + "EAP-TTLS: failed to initialize Phase 2 EAP method %u:%u", + vendor, method); return -1; } @@ -399,9 +402,23 @@ static int eap_ttls_phase2_request_eap(struct eap_sm *sm, case EAP_TYPE_IDENTITY: *resp = eap_sm_buildIdentity(sm, hdr->identifier, 1); break; + case EAP_TYPE_EXPANDED: + if (len < sizeof(struct eap_hdr) + 8) { + wpa_printf(MSG_INFO, + "EAP-TTLS: Too short Phase 2 request (expanded header) (len=%lu)", + (unsigned long) len); + return -1; + } + if (eap_ttls_phase2_request_eap_method(sm, data, ret, hdr, len, + WPA_GET_BE24(pos + 1), + WPA_GET_BE32(pos + 4), + resp) < 0) + return -1; + break; default: if (eap_ttls_phase2_request_eap_method(sm, data, ret, hdr, len, - *pos, resp) < 0) + EAP_VENDOR_IETF, *pos, + resp) < 0) return -1; break; } From 252dd1b9760aae4ae05a01a6ba907e9cdeeb6707 Mon Sep 17 00:00:00 2001 From: Alexander Clouter Date: Fri, 16 Oct 2020 09:49:36 +0100 Subject: [PATCH 18/35] EAP-TTLS/PEAP peer: Fix failure when using session tickets under TLS 1.3 EAP peer does not expect data present when beginning the Phase 2 in EAP-{TTLS,PEAP} but in TLS 1.3 session tickets are sent after the handshake completes. There are several strategies that can be used to handle this, but this patch picks up from the discussion[1] and implements the proposed use of SSL_MODE_AUTO_RETRY. SSL_MODE_AUTO_RETRY has already been enabled by default in OpenSSL 1.1.1, but it needs to be enabled for older versions. The main OpenSSL wrapper change in tls_connection_decrypt() takes care of the new possible case with SSL_MODE_AUTO_RETRY for SSL_ERROR_WANT_READ to indicate that a non-application_data was processed. That is not really an error case with TLS 1.3, so allow it to complete and return an empty decrypted application data buffer. EAP-PEAP/TTLS processing can then use this to move ahead with starting Phase 2. [1] https://www.spinics.net/lists/hostap/msg05376.html Signed-off-by: Alexander Clouter --- components/wpa_supplicant/src/eap_peer/eap_peap.c | 4 ++++ components/wpa_supplicant/src/eap_peer/eap_ttls.c | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/components/wpa_supplicant/src/eap_peer/eap_peap.c b/components/wpa_supplicant/src/eap_peer/eap_peap.c index a4cf1a2376..3cc0ba2fff 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_peap.c +++ b/components/wpa_supplicant/src/eap_peer/eap_peap.c @@ -861,6 +861,10 @@ eap_peap_decrypt(struct eap_sm *sm, struct eap_peap_data *data, res = eap_peer_tls_decrypt(sm, &data->ssl, in_data, &in_decrypted); if (res) return res; + if (wpabuf_len(in_decrypted) == 0) { + wpabuf_free(in_decrypted); + return 1; + } continue_req: wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP", diff --git a/components/wpa_supplicant/src/eap_peer/eap_ttls.c b/components/wpa_supplicant/src/eap_peer/eap_ttls.c index 40f65725d8..a094ce5c61 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_ttls.c +++ b/components/wpa_supplicant/src/eap_peer/eap_ttls.c @@ -1390,6 +1390,7 @@ static int eap_ttls_decrypt(struct eap_sm *sm, struct eap_ttls_data *data, if ((in_data == NULL || wpabuf_len(in_data) == 0) && data->phase2_start) { +start: return eap_ttls_phase2_start(sm, data, ret, identifier, out_data); } @@ -1404,6 +1405,10 @@ static int eap_ttls_decrypt(struct eap_sm *sm, struct eap_ttls_data *data, retval = eap_peer_tls_decrypt(sm, &data->ssl, in_data, &in_decrypted); if (retval) goto done; + if (wpabuf_len(in_decrypted) == 0) { + wpabuf_free(in_decrypted); + goto start; + } continue_req: data->phase2_start = 0; From 0d904840180906c5835b062ee12cbd469f35b6b7 Mon Sep 17 00:00:00 2001 From: Alexander Clouter Date: Fri, 16 Oct 2020 09:49:38 +0100 Subject: [PATCH 19/35] EAP-PEAP: Key derivation per draft-ietf-emu-tls-eap-types-00 Use the TLS-Exporter with the label and context as defined in draft-ietf-emu-tls-eap-types-00 when deriving keys for PEAP with TLS 1.3. Signed-off-by: Alexander Clouter --- .../wpa_supplicant/src/eap_peer/eap_peap.c | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/components/wpa_supplicant/src/eap_peer/eap_peap.c b/components/wpa_supplicant/src/eap_peer/eap_peap.c index 3cc0ba2fff..312536a880 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_peap.c +++ b/components/wpa_supplicant/src/eap_peer/eap_peap.c @@ -1190,7 +1190,11 @@ 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}; + const char *label; + const u8 eap_tls13_context[1] = { EAP_TYPE_PEAP }; + const u8 *context = NULL; + size_t context_len = 0; + wpa_printf(MSG_DEBUG, "EAP-PEAP: TLS done, proceed to Phase 2"); eap_peap_free_key(data); /* draft-josefsson-ppext-eap-tls-eap-05.txt @@ -1199,16 +1203,25 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv, * PEAPv1 implementations seem to be using the old * label, "client EAP encryption", instead. Use the old * label by default, but allow it to be configured with - * phase1 parameter peaplabel=1. */ - if (data->peap_version > 1 || data->force_new_label) - os_strlcpy(label, "client PEAP encryption", 24); - else - os_strlcpy(label, "client EAP encryption", 24); + * phase1 parameter peaplabel=1. + * + * When using TLS 1.3, draft-ietf-emu-tls-eap-types + * defines a new set of label and context parameters. + */ + if (data->ssl.tls_v13) { + label = "EXPORTER_EAP_TLS_Key_Material"; + context = eap_tls13_context; + context_len = sizeof(eap_tls13_context); + } else if (data->force_new_label) { + label = "client PEAP encryption"; + } else { + label = "client EAP encryption"; + } wpa_printf(MSG_DEBUG, "EAP-PEAP: using label '%s' in " "key derivation", label); data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, label, - NULL, 0, + context, context_len, EAP_TLS_KEY_LEN + EAP_EMSK_LEN); if (data->key_data) { From 42e37285e58af9abfca459575b84b20bfd24906e Mon Sep 17 00:00:00 2001 From: Alexander Clouter Date: Fri, 16 Oct 2020 09:49:38 +0100 Subject: [PATCH 20/35] EAP-TTLS: Key derivation per draft-ietf-emu-tls-eap-types-00 Use the TLS-Exporter with the label and context as defined in draft-ietf-emu-tls-eap-types-00 when deriving keys for EAP-TTLS with TLS 1.3. Signed-off-by: Alexander Clouter --- .../wpa_supplicant/src/eap_peer/eap_ttls.c | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/components/wpa_supplicant/src/eap_peer/eap_ttls.c b/components/wpa_supplicant/src/eap_peer/eap_ttls.c index a094ce5c61..0c7f8a9dc9 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_ttls.c +++ b/components/wpa_supplicant/src/eap_peer/eap_ttls.c @@ -217,11 +217,24 @@ 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) { + const char *label; + const u8 eap_tls13_context[1] = { EAP_TYPE_TTLS }; + const u8 *context = NULL; + size_t context_len = 0; + + if (data->ssl.tls_v13) { + label = "EXPORTER_EAP_TLS_Key_Material"; + context = eap_tls13_context; + context_len = sizeof(eap_tls13_context); + } else { + label = "ttls keying material"; + } + eap_ttls_free_key(data); - data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, - "ttls keying material", - NULL, 0, - EAP_TLS_KEY_LEN); + data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, label, + context, context_len, + EAP_TLS_KEY_LEN + + EAP_EMSK_LEN); if (!data->key_data) { wpa_printf(MSG_ERROR, "EAP-TTLS: Failed to derive key"); return -1; From a5ee253d620d9d2f995c052c6094b3d20c204c82 Mon Sep 17 00:00:00 2001 From: Alexander Clouter Date: Fri, 16 Oct 2020 09:49:38 +0100 Subject: [PATCH 21/35] EAP: Extend Session-Id derivation with TLS 1.3 to PEAP and EAP-TTLS This newer Session-Id/Method-Id derivation is used with PEAP and EAP-TTLS when using TLS 1.3 per draft-ietf-emu-tls-eap-types-00, so do not limit this to only EAP-TLS. Signed-off-by: Alexander Clouter --- components/wpa_supplicant/src/eap_peer/eap_tls_common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/wpa_supplicant/src/eap_peer/eap_tls_common.c b/components/wpa_supplicant/src/eap_peer/eap_tls_common.c index c3081f7b17..d126df8213 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_tls_common.c +++ b/components/wpa_supplicant/src/eap_peer/eap_tls_common.c @@ -308,9 +308,9 @@ u8 * eap_peer_tls_derive_session_id(struct eap_sm *sm, struct tls_random keys; u8 *out; - if (eap_type == EAP_TYPE_TLS && data->tls_v13) { + if (data->tls_v13) { u8 *id, *method_id; - const u8 context[] = { EAP_TYPE_TLS }; + const u8 context[] = { eap_type }; /* Session-Id = || Method-Id * Method-Id = TLS-Exporter("EXPORTER_EAP_TLS_Method-Id", From 65248148f060fc9b6bc5598c75375cf0f064eb77 Mon Sep 17 00:00:00 2001 From: Alexander Clouter Date: Fri, 16 Oct 2020 09:49:38 +0100 Subject: [PATCH 22/35] EAP-TLS peer: Handle Commitment Message for TLS 1.3 Recognize the explicitly defined Commitment Message per draft-ietf-emu-eap-tls13-13 at the conclusion of the EAP-TLS with TLS 1.3. Signed-off-by: Alexander Clouter --- components/wpa_supplicant/src/eap_peer/eap_tls.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/components/wpa_supplicant/src/eap_peer/eap_tls.c b/components/wpa_supplicant/src/eap_peer/eap_tls.c index 82e307d422..b1ffba50a6 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_tls.c +++ b/components/wpa_supplicant/src/eap_peer/eap_tls.c @@ -242,15 +242,11 @@ static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv, return NULL; } - if (res == 2) { - /* Application data included in the handshake message (used by - * EAP-TLS 1.3 to indicate conclusion of the exchange). */ - wpa_hexdump_buf(MSG_DEBUG, "EAP-TLS: Received Application Data", - resp); - wpa_hexdump_buf(MSG_DEBUG, "EAP-TLS: Remaining tls_out data", - data->ssl.tls_out); + /* draft-ietf-emu-eap-tls13-13 Section 2.5 */ + if (res == 2 && data->ssl.tls_v13 && wpabuf_len(resp) == 1 && + *wpabuf_head_u8(resp) == 0) { + wpa_printf(MSG_DEBUG, "EAP-TLS: ACKing Commitment Message"); eap_peer_tls_reset_output(&data->ssl); - /* Send an ACK to allow the server to complete exchange */ res = 1; } From b17d6a1b3afabf12a8e637fd45bec5e5592d42f1 Mon Sep 17 00:00:00 2001 From: Alexander Clouter Date: Fri, 16 Oct 2020 09:49:38 +0100 Subject: [PATCH 23/35] EAP-TTLS peer: Handle Commitment Message for TLS 1.3 Recognize the explicitly defined Commitment Message per draft-ietf-emu-eap-tls13-13 at the conclusion of the EAP-TTLS with TLS 1.3. Signed-off-by: Alexander Clouter --- components/wpa_supplicant/src/eap_peer/eap_ttls.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/components/wpa_supplicant/src/eap_peer/eap_ttls.c b/components/wpa_supplicant/src/eap_peer/eap_ttls.c index 0c7f8a9dc9..4425da4514 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_ttls.c +++ b/components/wpa_supplicant/src/eap_peer/eap_ttls.c @@ -1423,6 +1423,16 @@ start: goto start; } + /* draft-ietf-emu-eap-tls13-13 Section 2.5 */ + if (data->ssl.tls_v13 && wpabuf_len(in_decrypted) == 1 && + *wpabuf_head_u8(in_decrypted) == 0) { + wpa_printf(MSG_DEBUG, + "EAP-TTLS: ACKing EAP-TLS Commitment Message"); + eap_peer_tls_reset_output(&data->ssl); + wpabuf_free(in_decrypted); + return 1; + } + continue_req: data->phase2_start = 0; From 9cb8c0545f679dcf33899e016b409831445ea8e8 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 5 Apr 2022 22:56:13 +0300 Subject: [PATCH 24/35] EAP-TLS: Update specification references to RFC 5216 and 9190 The previously used references were pointing to an obsoleted RFC and draft versions. Replace these with current versions. Signed-off-by: Jouni Malinen --- components/wpa_supplicant/src/eap_peer/eap_tls.c | 6 +++--- components/wpa_supplicant/src/eap_peer/eap_ttls.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/wpa_supplicant/src/eap_peer/eap_tls.c b/components/wpa_supplicant/src/eap_peer/eap_tls.c index b1ffba50a6..7939370ad9 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_tls.c +++ b/components/wpa_supplicant/src/eap_peer/eap_tls.c @@ -1,6 +1,6 @@ /* - * EAP peer method: EAP-TLS (RFC 2716) - * Copyright (c) 2004-2008, 2012-2015, Jouni Malinen + * EAP peer method: EAP-TLS (RFC 5216, RFC 9190) + * Copyright (c) 2004-2008, 2012-2019, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -242,7 +242,7 @@ static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv, return NULL; } - /* draft-ietf-emu-eap-tls13-13 Section 2.5 */ + /* RFC 9190 Section 2.5 */ if (res == 2 && data->ssl.tls_v13 && wpabuf_len(resp) == 1 && *wpabuf_head_u8(resp) == 0) { wpa_printf(MSG_DEBUG, "EAP-TLS: ACKing Commitment Message"); diff --git a/components/wpa_supplicant/src/eap_peer/eap_ttls.c b/components/wpa_supplicant/src/eap_peer/eap_ttls.c index 4425da4514..d04ae75c82 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_ttls.c +++ b/components/wpa_supplicant/src/eap_peer/eap_ttls.c @@ -1423,7 +1423,7 @@ start: goto start; } - /* draft-ietf-emu-eap-tls13-13 Section 2.5 */ + /* RFC 9190 Section 2.5 */ if (data->ssl.tls_v13 && wpabuf_len(in_decrypted) == 1 && *wpabuf_head_u8(in_decrypted) == 0) { wpa_printf(MSG_DEBUG, From 98183fe0620d456a056f90ba6f9cf7c525dc4e1e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 5 Apr 2022 23:05:45 +0300 Subject: [PATCH 25/35] EAP-TLS: Replace the Commitment Message term with RFC 9190 language While the drafts for RFC 9190 used a separate Commitment Message term, that term was removed from the published RFC. Update the debug prints to match that final language. Signed-off-by: Jouni Malinen --- components/wpa_supplicant/src/eap_peer/eap_tls.c | 3 ++- components/wpa_supplicant/src/eap_peer/eap_ttls.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/components/wpa_supplicant/src/eap_peer/eap_tls.c b/components/wpa_supplicant/src/eap_peer/eap_tls.c index 7939370ad9..dcb604e51c 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_tls.c +++ b/components/wpa_supplicant/src/eap_peer/eap_tls.c @@ -245,7 +245,8 @@ static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv, /* RFC 9190 Section 2.5 */ if (res == 2 && data->ssl.tls_v13 && wpabuf_len(resp) == 1 && *wpabuf_head_u8(resp) == 0) { - wpa_printf(MSG_DEBUG, "EAP-TLS: ACKing Commitment Message"); + wpa_printf(MSG_DEBUG, + "EAP-TLS: ACKing protected success indication (appl data 0x00)"); eap_peer_tls_reset_output(&data->ssl); res = 1; } diff --git a/components/wpa_supplicant/src/eap_peer/eap_ttls.c b/components/wpa_supplicant/src/eap_peer/eap_ttls.c index d04ae75c82..e664d57eff 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_ttls.c +++ b/components/wpa_supplicant/src/eap_peer/eap_ttls.c @@ -1427,7 +1427,7 @@ start: if (data->ssl.tls_v13 && wpabuf_len(in_decrypted) == 1 && *wpabuf_head_u8(in_decrypted) == 0) { wpa_printf(MSG_DEBUG, - "EAP-TTLS: ACKing EAP-TLS Commitment Message"); + "EAP-TLS: ACKing protected success indication (appl data 0x00)"); eap_peer_tls_reset_output(&data->ssl); wpabuf_free(in_decrypted); return 1; From 89fc940ec003fcadda0213ef0922ec8019cf7dcd Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 6 Apr 2022 15:14:18 +0300 Subject: [PATCH 26/35] EAP-TLS: Do not allow TLSv1.3 success without protected result indication RFC 9190 requires protected result indication to be used with TLSv1.3, so do not allow EAP-TLS to complete successfully if the server does not send that indication. Signed-off-by: Jouni Malinen --- components/wpa_supplicant/src/eap_peer/eap_tls.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/components/wpa_supplicant/src/eap_peer/eap_tls.c b/components/wpa_supplicant/src/eap_peer/eap_tls.c index dcb604e51c..8db2e1f417 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_tls.c +++ b/components/wpa_supplicant/src/eap_peer/eap_tls.c @@ -28,6 +28,7 @@ struct eap_tls_data { void *ssl_ctx; u8 eap_type; struct wpabuf *pending_resp; + bool prot_success_received; }; @@ -249,9 +250,13 @@ static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv, "EAP-TLS: ACKing protected success indication (appl data 0x00)"); eap_peer_tls_reset_output(&data->ssl); res = 1; + ret->methodState = METHOD_DONE; + ret->decision = DECISION_UNCOND_SUCC; + data->prot_success_received = true; } - if (tls_connection_established(data->ssl_ctx, data->ssl.conn)) + if (tls_connection_established(data->ssl_ctx, data->ssl.conn) && + (!data->ssl.tls_v13 || data->prot_success_received)) eap_tls_success(sm, data, ret); if (res == 1) { From 6658c3ed6335d33e9c7e3f370679b1ee8a4963ea Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 15 Apr 2022 23:37:23 +0300 Subject: [PATCH 27/35] Remove useless DH file configuration from TLS library wrappers These operations do not really have any effect since tls_connection_set_params() is used only in the TLS client case and the client receives the DH parameters from the server instead of local configuration. Signed-off-by: Jouni Malinen --- components/wpa_supplicant/src/crypto/tls_internal.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/components/wpa_supplicant/src/crypto/tls_internal.c b/components/wpa_supplicant/src/crypto/tls_internal.c index 8095b43bd2..d7c4743c2c 100644 --- a/components/wpa_supplicant/src/crypto/tls_internal.c +++ b/components/wpa_supplicant/src/crypto/tls_internal.c @@ -281,13 +281,6 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, return -1; } - if (tlsv1_set_dhparams(cred, params->dh_file, params->dh_blob, - params->dh_blob_len)) { - wpa_printf(MSG_INFO, "TLS: Failed to load DH parameters"); - tlsv1_cred_free(cred); - return -1; - } - if (tlsv1_client_set_cred(conn->client, cred) < 0) { tlsv1_cred_free(cred); return -1; From 8ff4837830d2f5ef43cfd0694f39a852d489158b Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 4 May 2022 00:05:09 +0300 Subject: [PATCH 28/35] Fix tls_connection_set_success_data() in TLS library wrappers Some of the TLS library wrappers defined only an empty function for tls_connection_set_success_data(). That could result in memory leaks in TLS server cases, so update these to do the minimal thing and free the provided buffer as unused. Signed-off-by: Jouni Malinen --- components/wpa_supplicant/src/crypto/tls_internal.c | 1 + 1 file changed, 1 insertion(+) diff --git a/components/wpa_supplicant/src/crypto/tls_internal.c b/components/wpa_supplicant/src/crypto/tls_internal.c index d7c4743c2c..64451a90d8 100644 --- a/components/wpa_supplicant/src/crypto/tls_internal.c +++ b/components/wpa_supplicant/src/crypto/tls_internal.c @@ -784,6 +784,7 @@ int tls_get_library_version(char *buf, size_t buf_len) void tls_connection_set_success_data(struct tls_connection *conn, struct wpabuf *data) { + wpabuf_free(data); } From b58dbf2808b04fbfd8eeb918861a3dc34226c434 Mon Sep 17 00:00:00 2001 From: Glenn Strauss Date: Tue, 8 Nov 2022 00:05:53 -0500 Subject: [PATCH 29/35] Update tls_connection_set_verify() documentation to verify_peer=2 This new value was added to verify peer certificate if it is provided, but not reject the TLS handshake if no peer certificate is provided. Signed-off-by: Glenn Strauss --- components/wpa_supplicant/src/crypto/tls.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/components/wpa_supplicant/src/crypto/tls.h b/components/wpa_supplicant/src/crypto/tls.h index eb86937390..872047ccba 100644 --- a/components/wpa_supplicant/src/crypto/tls.h +++ b/components/wpa_supplicant/src/crypto/tls.h @@ -356,7 +356,9 @@ int __must_check tls_global_set_verify(void *tls_ctx, int check_crl, * tls_connection_set_verify - Set certificate verification options * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() - * @verify_peer: 1 = verify peer certificate + * @verify_peer: 0 = do not verify peer certificate, 1 = verify peer + * certificate (require it to be provided), 2 = verify peer certificate if + * provided * @flags: Connection flags (TLS_CONN_*) * @session_ctx: Session caching context or %NULL to use default * @session_ctx_len: Length of @session_ctx in bytes. From b3e4aae7bb1ae40dddac86ee1f2c21a0fa59baff Mon Sep 17 00:00:00 2001 From: Glenn Strauss Date: Tue, 8 Nov 2022 00:05:54 -0500 Subject: [PATCH 30/35] TLS: Fix unsigned int underflow in internal TLS 1.0/1.1 implementation Taking sizeof(ptr) is incorrect to determine size of passed in hash and results in hlen getting set to a very large value since MD5_MAC_LEN > sizeof(ptr). Provide the actual size of the hash buffer from the caller to fix this. tls_key_x_server_params_hash() callers src/tls/tlsv1_client_read.c and src/tls/tlsv1_server_write.c both pass in a large enough hash (hash[64] or hash[100]) that this does not appear to have an impact, though it is still wrong. Signed-off-by: Glenn Strauss --- components/wpa_supplicant/src/tls/tlsv1_client_read.c | 3 ++- components/wpa_supplicant/src/tls/tlsv1_common.c | 6 ++++-- components/wpa_supplicant/src/tls/tlsv1_common.h | 3 ++- components/wpa_supplicant/src/tls/tlsv1_server_write.c | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/components/wpa_supplicant/src/tls/tlsv1_client_read.c b/components/wpa_supplicant/src/tls/tlsv1_client_read.c index 9eac82f16e..3394873655 100644 --- a/components/wpa_supplicant/src/tls/tlsv1_client_read.c +++ b/components/wpa_supplicant/src/tls/tlsv1_client_read.c @@ -776,7 +776,8 @@ static int tlsv1_process_diffie_hellman(struct tlsv1_client *conn, hlen = tls_key_x_server_params_hash( conn->rl.tls_version, conn->client_random, conn->server_random, server_params, - server_params_end - server_params, hash); + server_params_end - server_params, hash, + sizeof(hash)); } if (hlen < 0) diff --git a/components/wpa_supplicant/src/tls/tlsv1_common.c b/components/wpa_supplicant/src/tls/tlsv1_common.c index 06c9640c8d..933c2df9c6 100644 --- a/components/wpa_supplicant/src/tls/tlsv1_common.c +++ b/components/wpa_supplicant/src/tls/tlsv1_common.c @@ -380,7 +380,7 @@ int tlsv12_key_x_server_params_hash(u16 tls_version, u8 hash_alg, int tls_key_x_server_params_hash(u16 tls_version, const u8 *client_random, const u8 *server_random, const u8 *server_params, - size_t server_params_len, u8 *hash) + size_t server_params_len, u8 *hash, size_t hsz) { u8 *hpos; size_t hlen; @@ -395,6 +395,8 @@ int tls_key_x_server_params_hash(u16 tls_version, const u8 *client_random, crypto_hash_update(ctx, server_random, TLS_RANDOM_LEN); crypto_hash_update(ctx, server_params, server_params_len); hlen = MD5_MAC_LEN; + if (hsz < hlen) + return -1; if (crypto_hash_finish(ctx, hash, &hlen) < 0) return -1; hpos += hlen; @@ -405,7 +407,7 @@ int tls_key_x_server_params_hash(u16 tls_version, const u8 *client_random, crypto_hash_update(ctx, client_random, TLS_RANDOM_LEN); crypto_hash_update(ctx, server_random, TLS_RANDOM_LEN); crypto_hash_update(ctx, server_params, server_params_len); - hlen = hash + sizeof(hash) - hpos; + hlen = hsz - hlen; if (crypto_hash_finish(ctx, hpos, &hlen) < 0) return -1; hpos += hlen; diff --git a/components/wpa_supplicant/src/tls/tlsv1_common.h b/components/wpa_supplicant/src/tls/tlsv1_common.h index e30b15a030..4cfdc2d551 100644 --- a/components/wpa_supplicant/src/tls/tlsv1_common.h +++ b/components/wpa_supplicant/src/tls/tlsv1_common.h @@ -267,7 +267,8 @@ int tlsv12_key_x_server_params_hash(u16 tls_version, u8 hash_Alg, int tls_key_x_server_params_hash(u16 tls_version, const u8 *client_random, const u8 *server_random, const u8 *server_params, - size_t server_params_len, u8 *hash); + size_t server_params_len, + u8 *hash, size_t hsz); int tls_verify_signature(u16 tls_version, struct crypto_public_key *pk, const u8 *data, size_t data_len, const u8 *pos, size_t len, u8 *alert); diff --git a/components/wpa_supplicant/src/tls/tlsv1_server_write.c b/components/wpa_supplicant/src/tls/tlsv1_server_write.c index 8d36cf1353..545abae2ba 100644 --- a/components/wpa_supplicant/src/tls/tlsv1_server_write.c +++ b/components/wpa_supplicant/src/tls/tlsv1_server_write.c @@ -620,7 +620,7 @@ static int tls_write_server_key_exchange(struct tlsv1_server *conn, hlen = tls_key_x_server_params_hash( conn->rl.tls_version, conn->client_random, conn->server_random, server_params, - pos - server_params, hash); + pos - server_params, hash, sizeof(hash)); } if (hlen < 0) { From ec09cdf885f59af09fe315b3065c7a6aa05dfa53 Mon Sep 17 00:00:00 2001 From: Sarvesh Bodakhe Date: Sat, 11 Nov 2023 13:39:31 +0530 Subject: [PATCH 31/35] feat(wpa_supplicant): Add TLS v1.3 support for WiFi enterprise * Add TLS v1.3 support for following EAP methods: - EAP-TLS (RFC 9190) - EAP-PEAP (RFC 9427) - EAP-TTLS (RFC 9427) * Add mbedtls porting for TLS v1.3 exporter (RFC 8446 Section 7.5) * Add new Kconfig flag to enable TLS v1.3 for EAP methods * Advertise TLS v1.3 signature algorithms if TLS 1.3 is enabled for EAP methods * Advertise TLS v1.3 cipher suites if CONFIG_ESP_WIFI_EAP_TLS1_3 enabled * Add support to Ack protected success indication (workaround for EAP-TLS 1.3 and 1.2 compatibilty) --- components/esp_wifi/Kconfig | 14 + components/wpa_supplicant/CMakeLists.txt | 3 + .../esp_supplicant/src/crypto/tls_mbedtls.c | 282 ++++++++++++++++-- .../wpa_supplicant/src/eap_peer/eap_peap.c | 11 + .../wpa_supplicant/src/eap_peer/eap_tls.c | 12 +- .../wpa_supplicant/src/eap_peer/eap_ttls.c | 10 + 6 files changed, 309 insertions(+), 23 deletions(-) diff --git a/components/esp_wifi/Kconfig b/components/esp_wifi/Kconfig index cda9c5ecae..90082a1ef2 100644 --- a/components/esp_wifi/Kconfig +++ b/components/esp_wifi/Kconfig @@ -493,6 +493,20 @@ menu "Wi-Fi" TLS-v1.0, TLS-v1.1 versions. Incase your server is using one of these version, it is advisable to update your server. Please disable this option for compatibilty with older TLS versions. + + config ESP_WIFI_EAP_TLS1_3 + bool "Enable EAP-TLS v1.3 Support for WiFi Enterprise connection" + default n + select MBEDTLS_SSL_PROTO_TLS1_3 + depends on ESP_WIFI_MBEDTLS_TLS_CLIENT + help + Select this option to support EAP with TLS v1.3. + This configuration still supports compatibility with EAP-TLS v1.2. + Please note that enabling this configuration will cause every application which + uses TLS go for TLS1.3 if server supports that. TLS1.3 is still in development in mbedtls + and there may be interoperability issues with this. Please modify your application to set + max version as TLS1.2 if you want to enable TLS1.3 only for WiFi connection. + endif config ESP_WIFI_WAPI_PSK diff --git a/components/wpa_supplicant/CMakeLists.txt b/components/wpa_supplicant/CMakeLists.txt index 9e7d1c042d..8473340026 100644 --- a/components/wpa_supplicant/CMakeLists.txt +++ b/components/wpa_supplicant/CMakeLists.txt @@ -304,6 +304,9 @@ endif() if(CONFIG_ESP_WIFI_ENABLE_WPA3_OWE_STA) target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_OWE_STA) endif() +if(CONFIG_ESP_WIFI_EAP_TLS1_3) + target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_TLSV13) +endif() set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY LINK_INTERFACE_MULTIPLICITY 3) target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format") diff --git a/components/wpa_supplicant/esp_supplicant/src/crypto/tls_mbedtls.c b/components/wpa_supplicant/esp_supplicant/src/crypto/tls_mbedtls.c index 606af1a0e3..b2d94dd65f 100644 --- a/components/wpa_supplicant/esp_supplicant/src/crypto/tls_mbedtls.c +++ b/components/wpa_supplicant/esp_supplicant/src/crypto/tls_mbedtls.c @@ -37,10 +37,21 @@ #include "mbedtls/platform.h" #include "eap_peer/eap.h" +#ifdef CONFIG_TLSV13 +#include "psa/crypto.h" +#include "md_psa.h" +#include "ssl_tls13_keys.h" +#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \ + psa_to_ssl_errors, \ + psa_generic_status_to_mbedtls) +#endif /* CONFIG_TLSV13 */ + #define TLS_RANDOM_LEN 32 +#define TLS_HASH_MAX_SIZE 64 #define TLS_MASTER_SECRET_LEN 48 #define MAX_CIPHERSUITE 32 +#define MAX_EXPORTER_CONTEXT_LEN 65535 @@ -82,8 +93,10 @@ struct tls_connection { struct tls_data tls_io_data; unsigned char master_secret[TLS_MASTER_SECRET_LEN]; unsigned char randbytes[2 * TLS_RANDOM_LEN]; - mbedtls_tls_prf_types tls_prf_type; - mbedtls_md_type_t mac; + mbedtls_tls_prf_types tls_prf_type; +#ifdef CONFIG_TLSV13 + unsigned char exporter_master_secret[TLS_HASH_MAX_SIZE]; +#endif /* CONFIG_TLSV13 */ }; static void tls_mbedtls_cleanup(tls_context_t *tls) @@ -201,6 +214,43 @@ static int set_ca_cert(tls_context_t *tls, const unsigned char *cacert, size_t c #ifdef CONFIG_SUITEB192 static uint16_t tls_sig_algs_for_suiteb[] = { + +#ifdef CONFIG_TLSV13 +#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \ + defined(MBEDTLS_MD_CAN_SHA384) && \ + defined(PSA_WANT_ECC_SECP_R1_384) + MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384, + // == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA384) +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \ + defined(MBEDTLS_MD_CAN_SHA512) && \ + defined(PSA_WANT_ECC_SECP_R1_521) + MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512, + // == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA512) +#endif + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \ + defined(MBEDTLS_MD_CAN_SHA512) + MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512, +#endif \ + /* MBEDTLS_X509_RSASSA_PSS_SUPPORT && MBEDTLS_MD_CAN_SHA512 */ + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \ + defined(MBEDTLS_MD_CAN_SHA384) + MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384, +#endif \ + /* MBEDTLS_X509_RSASSA_PSS_SUPPORT && MBEDTLS_MD_CAN_SHA384 */ + +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_MD_CAN_SHA512) + MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512, +#endif /* MBEDTLS_RSA_C && MBEDTLS_MD_CAN_SHA512 */ + +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_MD_CAN_SHA384) + MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384, +#endif /* MBEDTLS_RSA_C && MBEDTLS_MD_CAN_SHA384 */ +#endif /* CONFIG_TLSV13 */ + #if defined(MBEDTLS_SHA512_C) #if defined(MBEDTLS_ECDSA_C) MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG( MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA512 ), @@ -235,6 +285,60 @@ static void tls_set_suiteb_config(tls_context_t *tls) #endif static uint16_t tls_sig_algs_for_eap[] = { + +#ifdef CONFIG_TLSV13 +#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \ + defined(MBEDTLS_MD_CAN_SHA256) && \ + defined(PSA_WANT_ECC_SECP_R1_256) + MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256, + // == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA256) +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \ + defined(MBEDTLS_MD_CAN_SHA384) && \ + defined(PSA_WANT_ECC_SECP_R1_384) + MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384, + // == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA384) +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \ + defined(MBEDTLS_MD_CAN_SHA512) && \ + defined(PSA_WANT_ECC_SECP_R1_521) + MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512, + // == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA512) +#endif + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \ + defined(MBEDTLS_MD_CAN_SHA512) + MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512, +#endif \ + /* MBEDTLS_X509_RSASSA_PSS_SUPPORT && MBEDTLS_MD_CAN_SHA512 */ + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \ + defined(MBEDTLS_MD_CAN_SHA384) + MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384, +#endif \ + /* MBEDTLS_X509_RSASSA_PSS_SUPPORT && MBEDTLS_MD_CAN_SHA384 */ + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \ + defined(MBEDTLS_MD_CAN_SHA256) + MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256, +#endif \ + /* MBEDTLS_X509_RSASSA_PSS_SUPPORT && MBEDTLS_MD_CAN_SHA256 */ + +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_MD_CAN_SHA512) + MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512, +#endif /* MBEDTLS_RSA_C && MBEDTLS_MD_CAN_SHA512 */ + +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_MD_CAN_SHA384) + MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384, +#endif /* MBEDTLS_RSA_C && MBEDTLS_MD_CAN_SHA384 */ + +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_MD_CAN_SHA256) + MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256, +#endif /* MBEDTLS_RSA_C && MBEDTLS_MD_CAN_SHA256 */ +#endif /* CONFIG_TLSV13 */ + #if defined(MBEDTLS_SHA512_C) #if defined(MBEDTLS_ECDSA_C) MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG( MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA512 ), @@ -300,8 +404,20 @@ static int tls_disable_key_usages(void *data, mbedtls_x509_crt *cert, int depth, } #endif /*CONFIG_ESP_WIFI_DISABLE_KEY_USAGE_CHECK*/ +#if defined(CONFIG_ESP_WIFI_EAP_TLS1_3) +#define TLS1_3_CIPHER_SUITES \ + MBEDTLS_TLS1_3_CHACHA20_POLY1305_SHA256, \ + MBEDTLS_TLS1_3_AES_256_GCM_SHA384, \ + MBEDTLS_TLS1_3_AES_128_GCM_SHA256, \ + MBEDTLS_TLS1_3_AES_128_CCM_8_SHA256, \ + MBEDTLS_TLS1_3_AES_128_CCM_SHA256 +#endif /* CONFIG_ESP_WIFI_EAP_TLS1_3 */ + static const int eap_ciphersuite_preference[] = { +#if defined(CONFIG_ESP_WIFI_EAP_TLS1_3) + TLS1_3_CIPHER_SUITES, +#endif /* CONFIG_ESP_WIFI_EAP_TLS1_3 */ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) #if defined(MBEDTLS_CCM_C) MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM, @@ -417,6 +533,9 @@ static const int eap_ciphersuite_preference[] = #ifdef CONFIG_SUITEB192 static const int suiteb_rsa_ciphersuite_preference[] = { +#if defined(CONFIG_ESP_WIFI_EAP_TLS1_3) + TLS1_3_CIPHER_SUITES, +#endif /* CONFIG_ESP_WIFI_EAP_TLS1_3 */ #if defined(MBEDTLS_GCM_C) #if defined(MBEDTLS_SHA512_C) MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, @@ -428,6 +547,9 @@ static const int suiteb_rsa_ciphersuite_preference[] = static const int suiteb_ecc_ciphersuite_preference[] = { +#if defined(CONFIG_ESP_WIFI_EAP_TLS1_3) + TLS1_3_CIPHER_SUITES, +#endif /* CONFIG_ESP_WIFI_EAP_TLS1_3 */ #if defined(MBEDTLS_GCM_C) #if defined(MBEDTLS_SHA512_C) MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, @@ -437,6 +559,9 @@ static const int suiteb_ecc_ciphersuite_preference[] = }; static const int suiteb_ciphersuite_preference[] = { +#if defined(CONFIG_ESP_WIFI_EAP_TLS1_3) + TLS1_3_CIPHER_SUITES, +#endif /* CONFIG_ESP_WIFI_EAP_TLS1_3 */ #if defined(MBEDTLS_GCM_C) #if defined(MBEDTLS_SHA512_C) MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, @@ -469,12 +594,23 @@ static void tls_set_ciphersuite(const struct tls_connection_params *cfg, tls_con } } else #endif +#ifdef CONFIG_TLSV13 + /* Enable TLS1.3 ciphers if TLS1.3 is enabled */ + mbedtls_ssl_conf_ciphersuites(&tls->conf, eap_ciphersuite_preference); +#else + /* Set cipher suites if User has explicitly set those + * TODO: public API to set EAP ciphers */ if (tls->ciphersuite[0]) { mbedtls_ssl_conf_ciphersuites(&tls->conf, tls->ciphersuite); } else if (mbedtls_pk_get_bitlen(&tls->clientkey) > 2048 || (tls->cacert_ptr && mbedtls_pk_get_bitlen(&tls->cacert_ptr->pk) > 2048)) { + /* Incase of big RSA keylen, ESP chips do not have sufficient processing + * power to use high computation ciphers. This code will limit the ciphers + * to less computational ones */ mbedtls_ssl_conf_ciphersuites(&tls->conf, eap_ciphersuite_preference); } + +#endif /* CONFIG_TLSV13 */ } static int set_client_config(const struct tls_connection_params *cfg, tls_context_t *tls) @@ -548,6 +684,22 @@ static int set_client_config(const struct tls_connection_params *cfg, tls_contex return 0; } +#ifdef CONFIG_TLSV13 +static void tls13_extract_exporter_master_secret(struct tls_connection *conn) +{ + mbedtls_ssl_context *ssl = &conn->tls->ssl; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; + psa_algorithm_t hash_alg = mbedtls_md_psa_alg_from_type(ciphersuite_info->mac); + + size_t hash_len = PSA_HASH_LENGTH(hash_alg); + assert(hash_len != 0); + + mbedtls_ssl_tls13_application_secrets *app_secrets = + &ssl->session_negotiate->app_secrets; + os_memcpy(conn->exporter_master_secret, app_secrets->exporter_master_secret, hash_len); +} +#endif /* CONFIG_TLSV13 */ + static void tls_key_derivation(void *ctx, mbedtls_ssl_key_export_type secret_type, const unsigned char *secret, @@ -562,6 +714,12 @@ static void tls_key_derivation(void *ctx, os_memcpy(conn->randbytes, client_random, TLS_RANDOM_LEN); os_memcpy(conn->randbytes + 32, server_random, TLS_RANDOM_LEN); conn->tls_prf_type = tls_prf_type; + +#ifdef CONFIG_TLSV13 + if (secret_type == MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_APPLICATION_TRAFFIC_SECRET) { + tls13_extract_exporter_master_secret(conn); + } +#endif /* CONFIG_TLSV13 */ } static int tls_create_mbedtls_handle(struct tls_connection *conn, @@ -593,6 +751,12 @@ static int tls_create_mbedtls_handle(struct tls_connection *conn, mbedtls_ssl_conf_rng(&tls->conf, mbedtls_ctr_drbg_random, &tls->ctr_drbg); +#if defined(CONFIG_MBEDTLS_SSL_PROTO_TLS1_3) && !defined(CONFIG_TLSV13) + /* Disable TLSv1.3 even when enabled in MbedTLS and not enabled in WiFi config. + * TODO: Remove Kconfig option for TLSv1.3 when it is matured enough */ + mbedtls_ssl_conf_max_tls_version(&tls->conf, MBEDTLS_SSL_VERSION_TLS1_2); +#endif /* CONFIG_MBEDTLS_SSL_PROTO_TLS1_3 && !CONFIG_TLSV13 */ + ret = mbedtls_ssl_setup(&tls->ssl, &tls->conf); if (ret != 0) { wpa_printf(MSG_ERROR, "mbedtls_ssl_setup returned -0x%x", -ret); @@ -749,17 +913,8 @@ struct wpabuf * tls_connection_handshake(void *tls_ctx, /* Multiple reads */ while (!mbedtls_ssl_is_handshake_over(&tls->ssl)) { cli_state = tls->ssl.MBEDTLS_PRIVATE(state); - if (cli_state == MBEDTLS_SSL_CLIENT_CERTIFICATE) { - /* Read random data before session completes, not present after handshake */ - if (tls->ssl.MBEDTLS_PRIVATE(handshake)) { - os_memcpy(conn->randbytes, tls->ssl.MBEDTLS_PRIVATE(handshake)->randbytes, - TLS_RANDOM_LEN * 2); - conn->mac = tls->ssl.MBEDTLS_PRIVATE(handshake)->ciphersuite_info->mac; - } - } ret = mbedtls_ssl_handshake_step(&tls->ssl); - - if (ret < 0) { + if (ret < 0) break; } #ifdef CONFIG_ESP_WIFI_ENT_FREE_DYNAMIC_BUFFER @@ -782,7 +937,28 @@ struct wpabuf * tls_connection_handshake(void *tls_ctx, if (!conn->tls_io_data.out_data) { wpa_printf(MSG_INFO, "application data is null, adding one byte for ack"); u8 *dummy = os_zalloc(1); + if (dummy == NULL) { + wpa_printf(MSG_INFO, "%s: memory allocation failure. line:%d", __func__, __LINE__); + goto end; + } + +#ifdef CONFIG_TLSV13 + if (mbedtls_ssl_get_version_number(&conn->tls->ssl) == MBEDTLS_SSL_VERSION_TLS1_3) { + *appl_data = wpabuf_alloc_ext_data(dummy, 1); + if (appl_data == NULL) { + wpa_printf(MSG_INFO, "%s: memory allocation failure. line:%d", __func__, __LINE__); + os_free(dummy); + goto end; + } + return NULL; + } +#endif /* CONFIG_TLSV13 */ conn->tls_io_data.out_data = wpabuf_alloc_ext_data(dummy, 0); + if (conn->tls_io_data.out_data == NULL) { + wpa_printf(MSG_INFO, "%s: memory allocation failure. line:%d", __func__, __LINE__); + os_free(dummy); + goto end; + } } end: @@ -1006,25 +1182,26 @@ static int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, size_t seed_len = 2 * TLS_RANDOM_LEN; mbedtls_ssl_context *ssl = &conn->tls->ssl; - if (context_len > 65535) + if (context_len > MAX_EXPORTER_CONTEXT_LEN) { return -1; + } - if (context) + if (context) { + // The magic value 2 represents the memory required to store the context length. seed_len += 2 + context_len; - - seed = os_malloc(seed_len); - if (!seed) { - return -1; } if (!ssl) { wpa_printf(MSG_ERROR, "TLS: %s, session ingo is null", __func__); - os_free(seed); return -1; } if (!mbedtls_ssl_is_handshake_over(ssl)) { wpa_printf(MSG_ERROR, "TLS: %s, incorrect tls state=%d", __func__, ssl->MBEDTLS_PRIVATE(state)); - os_free(seed); + return -1; + } + + seed = os_malloc(seed_len); + if (!seed) { return -1; } @@ -1046,7 +1223,7 @@ static int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, wpa_hexdump_key(MSG_MSGDUMP, "master", ssl->MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(master), TLS_MASTER_SECRET_LEN); ret = mbedtls_ssl_tls_prf(conn->tls_prf_type, conn->master_secret, TLS_MASTER_SECRET_LEN, - label, seed, 2 * TLS_RANDOM_LEN, out, out_len); + label, seed, seed_len, out, out_len); os_free(seed); if (ret < 0) { @@ -1058,11 +1235,72 @@ static int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, return ret; } +#ifdef CONFIG_TLSV13 +/* RFC 8446 Section 7.5 */ +static int tls13_connection_export_key(void *tls_ctx, struct tls_connection *conn, + const char *label, const u8 *context, + size_t context_len, u8 *out, size_t out_len) +{ + int ret; + mbedtls_ssl_context *ssl = &conn->tls->ssl; + psa_algorithm_t hash_alg; + size_t hash_len; + unsigned char tmp_secret[PSA_MAC_MAX_SIZE] = { 0 }; + unsigned char hashed_context[PSA_HASH_MAX_SIZE] = { 0 }; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; + + hash_alg = mbedtls_md_psa_alg_from_type(ciphersuite_info->mac); + hash_len = PSA_HASH_LENGTH(hash_alg); + + ret = mbedtls_ssl_tls13_derive_secret(hash_alg, + conn->exporter_master_secret, hash_len, + (unsigned char const *) label, (size_t) strlen(label), + NULL, 0, + MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED, + tmp_secret, hash_len); + + if (ret != 0) { + wpa_printf(MSG_ERROR, "%s(): mbedtls_ssl_tls13_derive_secret() failed", + __func__); + return ret; + } + + status = psa_hash_compute(hash_alg, context, context_len, hashed_context, + PSA_HASH_LENGTH(hash_alg), &context_len); + if (status != PSA_SUCCESS) { + wpa_printf(MSG_ERROR, "%s(): psa_hash_compute() failed", + __func__); + ret = PSA_TO_MBEDTLS_ERR(status); + return ret; + } + + ret = mbedtls_ssl_tls13_hkdf_expand_label(hash_alg, + tmp_secret, hash_len, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(exporter), + hashed_context, context_len, + out, out_len); + + if (ret != 0) { + wpa_printf(MSG_ERROR, "%s(): psa_hash_compute() failed", + __func__); + return ret; + } + return 0; +} +#endif /* CONFIG_TLSV13 */ + int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn, const char *label, const u8 *context, size_t context_len, u8 *out, size_t out_len) { - return tls_connection_prf(tls_ctx, conn, label,context, context_len, +#ifdef CONFIG_TLSV13 + if (mbedtls_ssl_get_version_number(&conn->tls->ssl) == MBEDTLS_SSL_VERSION_TLS1_3) + return tls13_connection_export_key(tls_ctx, conn, label, context, context_len, + out, out_len); +#endif /* CONFIG_TLSV13 */ + return tls_connection_prf(tls_ctx, conn, label, context, context_len, 0, out, out_len); } diff --git a/components/wpa_supplicant/src/eap_peer/eap_peap.c b/components/wpa_supplicant/src/eap_peer/eap_peap.c index 312536a880..6c8a232024 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_peap.c +++ b/components/wpa_supplicant/src/eap_peer/eap_peap.c @@ -18,6 +18,10 @@ #include "eap_peer/eap_config.h" #include "eap_peer/eap_methods.h" +#ifdef CONFIG_TLSV13 +#include "psa/crypto.h" +#endif /* CONFIG_TLSV13 */ + /* Maximum supported PEAP version * 0 = Microsoft's PEAP version 0; draft-kamath-pppext-peapv0-00.txt * 1 = draft-josefsson-ppext-eap-tls-eap-05.txt @@ -160,6 +164,13 @@ eap_peap_init(struct eap_sm *sm) { struct eap_peap_data *data; struct eap_peer_config *config = eap_get_config(sm); +#ifdef CONFIG_TLSV13 + psa_status_t status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + wpa_printf(MSG_ERROR, "EAP-PEAP: Failed to initialize PSA crypto, returned %d", (int) status); + return NULL; + } +#endif /* CONFIG_TLSV13 */ data = (struct eap_peap_data *)os_zalloc(sizeof(*data)); if (data == NULL) diff --git a/components/wpa_supplicant/src/eap_peer/eap_tls.c b/components/wpa_supplicant/src/eap_peer/eap_tls.c index 8db2e1f417..babf6fac34 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_tls.c +++ b/components/wpa_supplicant/src/eap_peer/eap_tls.c @@ -16,6 +16,10 @@ #include "eap_peer/eap_config.h" #include "eap_peer/eap_methods.h" +#ifdef CONFIG_TLSV13 +#include "psa/crypto.h" +#endif /* CONFIG_TLSV13 */ + static void eap_tls_deinit(struct eap_sm *sm, void *priv); @@ -36,7 +40,13 @@ static void * eap_tls_init(struct eap_sm *sm) { struct eap_tls_data *data; struct eap_peer_config *config = eap_get_config(sm); - +#ifdef CONFIG_TLSV13 + psa_status_t status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + wpa_printf(MSG_ERROR, "EAP-TLS: Failed to initialize PSA crypto, returned %d", (int) status); + return NULL; + } +#endif /* CONFIG_TLSV13 */ if (config == NULL || config->private_key == 0) { wpa_printf(MSG_INFO, "EAP-TLS: Private key not configured"); diff --git a/components/wpa_supplicant/src/eap_peer/eap_ttls.c b/components/wpa_supplicant/src/eap_peer/eap_ttls.c index e664d57eff..08f1cb504a 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_ttls.c +++ b/components/wpa_supplicant/src/eap_peer/eap_ttls.c @@ -22,6 +22,9 @@ #include "eap_peer/eap_config.h" #include "eap_peer/eap_methods.h" +#ifdef CONFIG_TLSV13 +#include "psa/crypto.h" +#endif /* CONFIG_TLSV13 */ #define EAP_TTLS_VERSION 0 @@ -72,6 +75,13 @@ static void * eap_ttls_init(struct eap_sm *sm) { struct eap_ttls_data *data; struct eap_peer_config *config = eap_get_config(sm); +#ifdef CONFIG_TLSV13 + psa_status_t status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + wpa_printf(MSG_ERROR, "EAP-TTLS: Failed to initialize PSA crypto, returned %d", (int) status); + return NULL; + } +#endif /* CONFIG_TLSV13 */ data = (struct eap_ttls_data *)os_zalloc(sizeof(*data)); if (data == NULL) From 5ce95cae91489f6fcd8d2846d50ac7e66ef4c481 Mon Sep 17 00:00:00 2001 From: Sarvesh Bodakhe Date: Sat, 11 Nov 2023 13:37:30 +0530 Subject: [PATCH 32/35] fix(esp_wifi): Enable Server certificate validation when using mbedtls TLS v1.3 In TLS v1.2, It was possible to disable server certificate validation simply by using API 'mbedtls_ssl_conf_authmode'. But this behaviour is changed in TLS v1.3. We can not disable server certificate validation in TLS v1.3 using this API anymore. For more details, refer https://github.com/Mbed-TLS/mbedtls/issues/7075 --- .../main/wifi_enterprise_main.c | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/examples/wifi/wifi_enterprise/main/wifi_enterprise_main.c b/examples/wifi/wifi_enterprise/main/wifi_enterprise_main.c index b511c7c20a..aebd169395 100644 --- a/examples/wifi/wifi_enterprise/main/wifi_enterprise_main.c +++ b/examples/wifi/wifi_enterprise/main/wifi_enterprise_main.c @@ -57,10 +57,17 @@ static const char *TAG = "example"; To embed it in the app binary, the PEM, CRT and KEY file is named in the component.mk COMPONENT_EMBED_TXTFILES variable. */ -#ifdef CONFIG_EXAMPLE_VALIDATE_SERVER_CERT +#if defined(CONFIG_EXAMPLE_VALIDATE_SERVER_CERT) || \ + defined(CONFIG_EXAMPLE_WPA3_ENTERPRISE) || \ + defined(CONFIG_EXAMPLE_WPA3_192BIT_ENTERPRISE) || \ + defined(CONFIG_ESP_WIFI_EAP_TLS1_3) +#define SERVER_CERT_VALIDATION_ENABLED +#endif + +#ifdef SERVER_CERT_VALIDATION_ENABLED extern uint8_t ca_pem_start[] asm("_binary_ca_pem_start"); extern uint8_t ca_pem_end[] asm("_binary_ca_pem_end"); -#endif /* CONFIG_EXAMPLE_VALIDATE_SERVER_CERT */ +#endif /* SERVER_CERT_VALIDATION_ENABLED */ #ifdef CONFIG_EXAMPLE_EAP_METHOD_TLS extern uint8_t client_crt_start[] asm("_binary_client_crt_start"); @@ -88,9 +95,9 @@ static void event_handler(void* arg, esp_event_base_t event_base, static void initialise_wifi(void) { -#ifdef CONFIG_EXAMPLE_VALIDATE_SERVER_CERT +#ifdef SERVER_CERT_VALIDATION_ENABLED unsigned int ca_pem_bytes = ca_pem_end - ca_pem_start; -#endif /* CONFIG_EXAMPLE_VALIDATE_SERVER_CERT */ +#endif /* SERVER_CERT_VALIDATION_ENABLED */ #ifdef CONFIG_EXAMPLE_EAP_METHOD_TLS unsigned int client_crt_bytes = client_crt_end - client_crt_start; @@ -123,11 +130,9 @@ static void initialise_wifi(void) ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) ); ESP_ERROR_CHECK(esp_eap_client_set_identity((uint8_t *)EXAMPLE_EAP_ID, strlen(EXAMPLE_EAP_ID)) ); -#if defined(CONFIG_EXAMPLE_VALIDATE_SERVER_CERT) || \ - defined(CONFIG_EXAMPLE_WPA3_ENTERPRISE) || \ - defined(CONFIG_EXAMPLE_WPA3_192BIT_ENTERPRISE) +#ifdef SERVER_CERT_VALIDATION_ENABLED ESP_ERROR_CHECK(esp_eap_client_set_ca_cert(ca_pem_start, ca_pem_bytes) ); -#endif /* CONFIG_EXAMPLE_VALIDATE_SERVER_CERT */ /* EXAMPLE_WPA3_ENTERPRISE */ +#endif /* SERVER_CERT_VALIDATION_ENABLED */ #ifdef CONFIG_EXAMPLE_EAP_METHOD_TLS ESP_ERROR_CHECK(esp_eap_client_set_certificate_and_key(client_crt_start, client_crt_bytes, From 5903e9ea2bca62866bb1ee3348131b204bcdbc0b Mon Sep 17 00:00:00 2001 From: Sarvesh Bodakhe Date: Thu, 1 Feb 2024 15:34:45 +0530 Subject: [PATCH 33/35] feat(wpa_supplicant): Make CONFIG_ESP_WIFI_EAP_TLS1_3 an experimental feature --- Kconfig | 1 + components/esp_wifi/Kconfig | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Kconfig b/Kconfig index fe4e12f863..56d3f1a64d 100644 --- a/Kconfig +++ b/Kconfig @@ -627,3 +627,4 @@ mainmenu "Espressif IoT Development Framework Configuration" - CONFIG_SPIRAM_SPEED_120M && CONFIG_SPIRAM_MODE_OCT - CONFIG_BOOTLOADER_CACHE_32BIT_ADDR_QUAD_FLASH - CONFIG_MBEDTLS_USE_CRYPTO_ROM_IMPL + - CONFIG_ESP_WIFI_EAP_TLS1_3 diff --git a/components/esp_wifi/Kconfig b/components/esp_wifi/Kconfig index 90082a1ef2..580a90f8d0 100644 --- a/components/esp_wifi/Kconfig +++ b/components/esp_wifi/Kconfig @@ -498,7 +498,7 @@ menu "Wi-Fi" bool "Enable EAP-TLS v1.3 Support for WiFi Enterprise connection" default n select MBEDTLS_SSL_PROTO_TLS1_3 - depends on ESP_WIFI_MBEDTLS_TLS_CLIENT + depends on ESP_WIFI_MBEDTLS_TLS_CLIENT && IDF_EXPERIMENTAL_FEATURES help Select this option to support EAP with TLS v1.3. This configuration still supports compatibility with EAP-TLS v1.2. From 05b882baeac3821db7b1bf089050c445567394ce Mon Sep 17 00:00:00 2001 From: Sarvesh Bodakhe Date: Tue, 6 Feb 2024 13:12:12 +0530 Subject: [PATCH 34/35] fix(wpa_supplicant): Update cipher suite list for TLSv1.3 suiteb and some refactoring - Use MBEDTLS_TLS1_3_AES_256_GCM_SHA384 cipher for TLSv1.3-suiteb - Call psa_crypto_init() in tls_connection_init() to reduce redundancy --- components/esp_wifi/Kconfig | 24 ++++++++--------- .../esp_supplicant/src/crypto/tls_mbedtls.c | 26 ++++++++++++------- .../wpa_supplicant/src/eap_peer/eap_peap.c | 11 -------- .../wpa_supplicant/src/eap_peer/eap_tls.c | 12 +-------- .../wpa_supplicant/src/eap_peer/eap_ttls.c | 10 ------- 5 files changed, 30 insertions(+), 53 deletions(-) diff --git a/components/esp_wifi/Kconfig b/components/esp_wifi/Kconfig index 580a90f8d0..42b7fcbb38 100644 --- a/components/esp_wifi/Kconfig +++ b/components/esp_wifi/Kconfig @@ -494,18 +494,18 @@ menu "Wi-Fi" it is advisable to update your server. Please disable this option for compatibilty with older TLS versions. - config ESP_WIFI_EAP_TLS1_3 - bool "Enable EAP-TLS v1.3 Support for WiFi Enterprise connection" - default n - select MBEDTLS_SSL_PROTO_TLS1_3 - depends on ESP_WIFI_MBEDTLS_TLS_CLIENT && IDF_EXPERIMENTAL_FEATURES - help - Select this option to support EAP with TLS v1.3. - This configuration still supports compatibility with EAP-TLS v1.2. - Please note that enabling this configuration will cause every application which - uses TLS go for TLS1.3 if server supports that. TLS1.3 is still in development in mbedtls - and there may be interoperability issues with this. Please modify your application to set - max version as TLS1.2 if you want to enable TLS1.3 only for WiFi connection. + config ESP_WIFI_EAP_TLS1_3 + bool "Enable EAP-TLS v1.3 Support for WiFi Enterprise connection" + default n + select MBEDTLS_SSL_PROTO_TLS1_3 + depends on ESP_WIFI_MBEDTLS_TLS_CLIENT && IDF_EXPERIMENTAL_FEATURES + help + Select this option to support EAP with TLS v1.3. + This configuration still supports compatibility with EAP-TLS v1.2. + Please note that enabling this configuration will cause every application which + uses TLS go for TLS1.3 if server supports that. TLS1.3 is still in development in mbedtls + and there may be interoperability issues with this. Please modify your application to set + max version as TLS1.2 if you want to enable TLS1.3 only for WiFi connection. endif diff --git a/components/wpa_supplicant/esp_supplicant/src/crypto/tls_mbedtls.c b/components/wpa_supplicant/esp_supplicant/src/crypto/tls_mbedtls.c index b2d94dd65f..0af9052ca2 100644 --- a/components/wpa_supplicant/esp_supplicant/src/crypto/tls_mbedtls.c +++ b/components/wpa_supplicant/esp_supplicant/src/crypto/tls_mbedtls.c @@ -405,10 +405,10 @@ static int tls_disable_key_usages(void *data, mbedtls_x509_crt *cert, int depth, #endif /*CONFIG_ESP_WIFI_DISABLE_KEY_USAGE_CHECK*/ #if defined(CONFIG_ESP_WIFI_EAP_TLS1_3) -#define TLS1_3_CIPHER_SUITES \ +#define TLS1_3_CIPHER_SUITES \ MBEDTLS_TLS1_3_CHACHA20_POLY1305_SHA256, \ - MBEDTLS_TLS1_3_AES_256_GCM_SHA384, \ - MBEDTLS_TLS1_3_AES_128_GCM_SHA256, \ + MBEDTLS_TLS1_3_AES_256_GCM_SHA384, \ + MBEDTLS_TLS1_3_AES_128_GCM_SHA256, \ MBEDTLS_TLS1_3_AES_128_CCM_8_SHA256, \ MBEDTLS_TLS1_3_AES_128_CCM_SHA256 #endif /* CONFIG_ESP_WIFI_EAP_TLS1_3 */ @@ -534,7 +534,7 @@ static const int eap_ciphersuite_preference[] = static const int suiteb_rsa_ciphersuite_preference[] = { #if defined(CONFIG_ESP_WIFI_EAP_TLS1_3) - TLS1_3_CIPHER_SUITES, + MBEDTLS_TLS1_3_AES_256_GCM_SHA384, #endif /* CONFIG_ESP_WIFI_EAP_TLS1_3 */ #if defined(MBEDTLS_GCM_C) #if defined(MBEDTLS_SHA512_C) @@ -548,7 +548,7 @@ static const int suiteb_rsa_ciphersuite_preference[] = static const int suiteb_ecc_ciphersuite_preference[] = { #if defined(CONFIG_ESP_WIFI_EAP_TLS1_3) - TLS1_3_CIPHER_SUITES, + MBEDTLS_TLS1_3_AES_256_GCM_SHA384, #endif /* CONFIG_ESP_WIFI_EAP_TLS1_3 */ #if defined(MBEDTLS_GCM_C) #if defined(MBEDTLS_SHA512_C) @@ -560,7 +560,7 @@ static const int suiteb_ecc_ciphersuite_preference[] = static const int suiteb_ciphersuite_preference[] = { #if defined(CONFIG_ESP_WIFI_EAP_TLS1_3) - TLS1_3_CIPHER_SUITES, + MBEDTLS_TLS1_3_AES_256_GCM_SHA384, #endif /* CONFIG_ESP_WIFI_EAP_TLS1_3 */ #if defined(MBEDTLS_GCM_C) #if defined(MBEDTLS_SHA512_C) @@ -797,6 +797,13 @@ struct tls_connection * tls_connection_init(void *tls_ctx) wpa_printf(MSG_ERROR, "TLS: Failed to allocate connection memory"); return NULL; } +#ifdef CONFIG_TLSV13 + psa_status_t status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + wpa_printf(MSG_ERROR, "Failed to initialize PSA crypto, returned %d", (int) status); + return NULL; + } +#endif /* CONFIG_TLSV13 */ return conn; } @@ -902,7 +909,6 @@ struct wpabuf * tls_connection_handshake(void *tls_ctx, tls_context_t *tls = conn->tls; int ret = 0; struct wpabuf *resp; - int cli_state; /* data freed by sender */ conn->tls_io_data.out_data = NULL; @@ -912,9 +918,11 @@ struct wpabuf * tls_connection_handshake(void *tls_ctx, /* Multiple reads */ while (!mbedtls_ssl_is_handshake_over(&tls->ssl)) { - cli_state = tls->ssl.MBEDTLS_PRIVATE(state); +#ifdef CONFIG_ESP_WIFI_ENT_FREE_DYNAMIC_BUFFER + int cli_state = tls->ssl.MBEDTLS_PRIVATE(state); +#endif /* CONFIG_ESP_WIFI_ENT_FREE_DYNAMIC_BUFFER */ ret = mbedtls_ssl_handshake_step(&tls->ssl); - if (ret < 0) + if (ret < 0) { break; } #ifdef CONFIG_ESP_WIFI_ENT_FREE_DYNAMIC_BUFFER diff --git a/components/wpa_supplicant/src/eap_peer/eap_peap.c b/components/wpa_supplicant/src/eap_peer/eap_peap.c index 6c8a232024..312536a880 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_peap.c +++ b/components/wpa_supplicant/src/eap_peer/eap_peap.c @@ -18,10 +18,6 @@ #include "eap_peer/eap_config.h" #include "eap_peer/eap_methods.h" -#ifdef CONFIG_TLSV13 -#include "psa/crypto.h" -#endif /* CONFIG_TLSV13 */ - /* Maximum supported PEAP version * 0 = Microsoft's PEAP version 0; draft-kamath-pppext-peapv0-00.txt * 1 = draft-josefsson-ppext-eap-tls-eap-05.txt @@ -164,13 +160,6 @@ eap_peap_init(struct eap_sm *sm) { struct eap_peap_data *data; struct eap_peer_config *config = eap_get_config(sm); -#ifdef CONFIG_TLSV13 - psa_status_t status = psa_crypto_init(); - if (status != PSA_SUCCESS) { - wpa_printf(MSG_ERROR, "EAP-PEAP: Failed to initialize PSA crypto, returned %d", (int) status); - return NULL; - } -#endif /* CONFIG_TLSV13 */ data = (struct eap_peap_data *)os_zalloc(sizeof(*data)); if (data == NULL) diff --git a/components/wpa_supplicant/src/eap_peer/eap_tls.c b/components/wpa_supplicant/src/eap_peer/eap_tls.c index babf6fac34..8db2e1f417 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_tls.c +++ b/components/wpa_supplicant/src/eap_peer/eap_tls.c @@ -16,10 +16,6 @@ #include "eap_peer/eap_config.h" #include "eap_peer/eap_methods.h" -#ifdef CONFIG_TLSV13 -#include "psa/crypto.h" -#endif /* CONFIG_TLSV13 */ - static void eap_tls_deinit(struct eap_sm *sm, void *priv); @@ -40,13 +36,7 @@ static void * eap_tls_init(struct eap_sm *sm) { struct eap_tls_data *data; struct eap_peer_config *config = eap_get_config(sm); -#ifdef CONFIG_TLSV13 - psa_status_t status = psa_crypto_init(); - if (status != PSA_SUCCESS) { - wpa_printf(MSG_ERROR, "EAP-TLS: Failed to initialize PSA crypto, returned %d", (int) status); - return NULL; - } -#endif /* CONFIG_TLSV13 */ + if (config == NULL || config->private_key == 0) { wpa_printf(MSG_INFO, "EAP-TLS: Private key not configured"); diff --git a/components/wpa_supplicant/src/eap_peer/eap_ttls.c b/components/wpa_supplicant/src/eap_peer/eap_ttls.c index 08f1cb504a..e664d57eff 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_ttls.c +++ b/components/wpa_supplicant/src/eap_peer/eap_ttls.c @@ -22,9 +22,6 @@ #include "eap_peer/eap_config.h" #include "eap_peer/eap_methods.h" -#ifdef CONFIG_TLSV13 -#include "psa/crypto.h" -#endif /* CONFIG_TLSV13 */ #define EAP_TTLS_VERSION 0 @@ -75,13 +72,6 @@ static void * eap_ttls_init(struct eap_sm *sm) { struct eap_ttls_data *data; struct eap_peer_config *config = eap_get_config(sm); -#ifdef CONFIG_TLSV13 - psa_status_t status = psa_crypto_init(); - if (status != PSA_SUCCESS) { - wpa_printf(MSG_ERROR, "EAP-TTLS: Failed to initialize PSA crypto, returned %d", (int) status); - return NULL; - } -#endif /* CONFIG_TLSV13 */ data = (struct eap_ttls_data *)os_zalloc(sizeof(*data)); if (data == NULL) From 1d7117819323e8a432cbcde295f8295fd7fa7e1b Mon Sep 17 00:00:00 2001 From: Sarvesh Bodakhe Date: Wed, 7 Feb 2024 21:40:40 +0530 Subject: [PATCH 35/35] fix(wpa_supplicant): Add bugfixes related to ciphersuites in wifi enterprise - Avoid downgrading TLS ciphersuites when client RSA keys are larger than RSA-2048 bit. - Note that when using bigger certificates on low-power chips without crypto hardware acceleration, it is recommended to adjust the task watchdog timer (TWDT) if it is enabled. For precise information on timing requirements, you can check performance numbers at https://github.com/espressif/mbedtls/wiki/Performance-Numbers. --- components/esp_wifi/Kconfig | 5 + .../esp_supplicant/src/crypto/tls_mbedtls.c | 137 ------------------ examples/wifi/wifi_enterprise/README.md | 3 + 3 files changed, 8 insertions(+), 137 deletions(-) diff --git a/components/esp_wifi/Kconfig b/components/esp_wifi/Kconfig index 42b7fcbb38..95d00e3d79 100644 --- a/components/esp_wifi/Kconfig +++ b/components/esp_wifi/Kconfig @@ -643,6 +643,11 @@ menu "Wi-Fi" disabling this will reduce binary size. disabling this will disable the use of any esp_wifi_sta_wpa2_ent_* (as APIs will be meaningless) + Note that when using bigger certificates on low-power chips without crypto + hardware acceleration, it is recommended to adjust the task watchdog timer (TWDT) + if it is enabled. For precise information on timing requirements, you can check + performance numbers at https://github.com/espressif/mbedtls/wiki/Performance-Numbers. + config ESP_WIFI_ENT_FREE_DYNAMIC_BUFFER bool "Free dynamic buffers during WiFi enterprise connection" depends on ESP_WIFI_ENTERPRISE_SUPPORT diff --git a/components/wpa_supplicant/esp_supplicant/src/crypto/tls_mbedtls.c b/components/wpa_supplicant/esp_supplicant/src/crypto/tls_mbedtls.c index 0af9052ca2..b51e016f98 100644 --- a/components/wpa_supplicant/esp_supplicant/src/crypto/tls_mbedtls.c +++ b/components/wpa_supplicant/esp_supplicant/src/crypto/tls_mbedtls.c @@ -404,132 +404,6 @@ static int tls_disable_key_usages(void *data, mbedtls_x509_crt *cert, int depth, } #endif /*CONFIG_ESP_WIFI_DISABLE_KEY_USAGE_CHECK*/ -#if defined(CONFIG_ESP_WIFI_EAP_TLS1_3) -#define TLS1_3_CIPHER_SUITES \ - MBEDTLS_TLS1_3_CHACHA20_POLY1305_SHA256, \ - MBEDTLS_TLS1_3_AES_256_GCM_SHA384, \ - MBEDTLS_TLS1_3_AES_128_GCM_SHA256, \ - MBEDTLS_TLS1_3_AES_128_CCM_8_SHA256, \ - MBEDTLS_TLS1_3_AES_128_CCM_SHA256 -#endif /* CONFIG_ESP_WIFI_EAP_TLS1_3 */ - -static const int eap_ciphersuite_preference[] = -{ -#if defined(CONFIG_ESP_WIFI_EAP_TLS1_3) - TLS1_3_CIPHER_SUITES, -#endif /* CONFIG_ESP_WIFI_EAP_TLS1_3 */ -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) -#if defined(MBEDTLS_CCM_C) - MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CBC) - MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, - MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CBC) - MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, - MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, -#endif - -#if defined(MBEDTLS_GCM_C) - MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, -#endif -#if defined(MBEDTLS_CCM_C) - MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CBC) - MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, - MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, -#endif -#if defined(MBEDTLS_CCM_C) - MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8, -#endif -#endif -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) - MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM, - MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA, - MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8, - - MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, - MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM, - MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, - MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8, -#endif -#if defined(MBEDTLS_CCM_C) - MBEDTLS_TLS_RSA_WITH_AES_256_CCM, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CBC) - MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256, - MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, -#endif -#if defined(MBEDTLS_CCM_C) - MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8, -#endif - -#if defined(MBEDTLS_GCM_C) - MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, -#endif -#if defined(MBEDTLS_CCM_C) - MBEDTLS_TLS_RSA_WITH_AES_128_CCM, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CBC) - MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256, - MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, -#endif -#if defined(MBEDTLS_GCM_C) - MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CBC) - MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, - MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, -#endif -#if defined(MBEDTLS_GCM_C) - MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CBC) - MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, - MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, -#endif -#if defined(MBEDTLS_CCM_C) - MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8, -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) -#if defined(MBEDTLS_GCM_C) - MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CBC) - MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, - MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA, -#endif - /* The PSK suites */ -#if defined(MBEDTLS_CCM_C) - MBEDTLS_TLS_PSK_WITH_AES_256_CCM, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CBC) - MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, -#endif -#if defined(MBEDTLS_CCM_C) - MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, -#endif - -#if defined(MBEDTLS_GCM_C) - MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256, -#endif -#if defined(MBEDTLS_CCM_C) - MBEDTLS_TLS_PSK_WITH_AES_128_CCM, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CBC) - MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256, - MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, -#endif -#if defined(MBEDTLS_CCM_C) - MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, -#endif -#endif - 0 -}; - #ifdef CONFIG_SUITEB192 static const int suiteb_rsa_ciphersuite_preference[] = { @@ -594,23 +468,12 @@ static void tls_set_ciphersuite(const struct tls_connection_params *cfg, tls_con } } else #endif -#ifdef CONFIG_TLSV13 - /* Enable TLS1.3 ciphers if TLS1.3 is enabled */ - mbedtls_ssl_conf_ciphersuites(&tls->conf, eap_ciphersuite_preference); -#else /* Set cipher suites if User has explicitly set those * TODO: public API to set EAP ciphers */ if (tls->ciphersuite[0]) { mbedtls_ssl_conf_ciphersuites(&tls->conf, tls->ciphersuite); - } else if (mbedtls_pk_get_bitlen(&tls->clientkey) > 2048 || - (tls->cacert_ptr && mbedtls_pk_get_bitlen(&tls->cacert_ptr->pk) > 2048)) { - /* Incase of big RSA keylen, ESP chips do not have sufficient processing - * power to use high computation ciphers. This code will limit the ciphers - * to less computational ones */ - mbedtls_ssl_conf_ciphersuites(&tls->conf, eap_ciphersuite_preference); } -#endif /* CONFIG_TLSV13 */ } static int set_client_config(const struct tls_connection_params *cfg, tls_context_t *tls) diff --git a/examples/wifi/wifi_enterprise/README.md b/examples/wifi/wifi_enterprise/README.md index 178b8d6ebe..6522f19494 100644 --- a/examples/wifi/wifi_enterprise/README.md +++ b/examples/wifi/wifi_enterprise/README.md @@ -10,6 +10,9 @@ **WPA3 Enterprise(192 bit)**: WPA3 Enterprise + AES256 Keys(GCMP256/CCMP256) + BIP256 + RSA3096/EC certs + NSA SuiteB ciphers in EAP authentication. +*Note:* +Note that when using bigger certificates on low-power chips without crypto hardware acceleration, it is recommended to adjust the task watchdog timer (TWDT) if it is enabled. For precise information on timing requirements, you can check performance numbers at https://github.com/espressif/mbedtls/wiki/Performance-Numbers. + # WiFi Enterprise Example This example shows how ESP32 connects to AP with Wi-Fi enterprise encryption. The example does the following steps: