mirror of
https://github.com/espressif/esp-idf
synced 2025-03-10 09:39:10 -04:00
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-<id>:External server certificate validation needed for SSID <ssid> Before that event, the server certificate chain is provided with the CTRL-EVENT-EAP-PEER-CERT events that include the cert=<hexdump> 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-<id>:<good|bad> 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 <j@w1.fi>
This commit is contained in:
parent
a7355d3aba
commit
5c0fb10902
@ -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
|
||||
};
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* EAP peer method: EAP-PEAP (draft-josefsson-pppext-eap-tls-eap-10.txt)
|
||||
* Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* EAP peer method: EAP-TLS (RFC 2716)
|
||||
* Copyright (c) 2004-2008, 2012, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2004-2008, 2012-2015, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* 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);
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* EAP peer method: EAP-TTLS (RFC 5281)
|
||||
* Copyright (c) 2004-2011, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* 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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user