2008-02-28 02:34:43 +01:00
|
|
|
/*
|
|
|
|
* EAP peer method: EAP-TLS (RFC 2716)
|
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>
2015-12-12 17:16:54 +01:00
|
|
|
* Copyright (c) 2004-2008, 2012-2015, Jouni Malinen <j@w1.fi>
|
2008-02-28 02:34:43 +01:00
|
|
|
*
|
2012-02-11 15:46:35 +01:00
|
|
|
* This software may be distributed under the terms of the BSD license.
|
|
|
|
* See README for more details.
|
2008-02-28 02:34:43 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "includes.h"
|
|
|
|
|
|
|
|
#include "common.h"
|
2009-11-29 22:04:43 +01:00
|
|
|
#include "crypto/tls.h"
|
2008-02-28 02:34:43 +01:00
|
|
|
#include "eap_i.h"
|
|
|
|
#include "eap_tls_common.h"
|
|
|
|
#include "eap_config.h"
|
|
|
|
|
|
|
|
|
|
|
|
static void eap_tls_deinit(struct eap_sm *sm, void *priv);
|
|
|
|
|
|
|
|
|
|
|
|
struct eap_tls_data {
|
|
|
|
struct eap_ssl_data ssl;
|
|
|
|
u8 *key_data;
|
2013-02-06 17:52:33 +01:00
|
|
|
u8 *session_id;
|
|
|
|
size_t id_len;
|
2012-04-07 19:57:02 +02:00
|
|
|
void *ssl_ctx;
|
2012-08-22 21:34:11 +02:00
|
|
|
u8 eap_type;
|
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>
2015-12-12 17:16:54 +01:00
|
|
|
struct wpabuf *pending_resp;
|
2008-02-28 02:34:43 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static void * eap_tls_init(struct eap_sm *sm)
|
|
|
|
{
|
|
|
|
struct eap_tls_data *data;
|
|
|
|
struct eap_peer_config *config = eap_get_config(sm);
|
|
|
|
if (config == NULL ||
|
|
|
|
((sm->init_phase2 ? config->private_key2 : config->private_key)
|
2008-11-18 15:53:32 +01:00
|
|
|
== NULL &&
|
|
|
|
(sm->init_phase2 ? config->engine2 : config->engine) == 0)) {
|
2008-02-28 02:34:43 +01:00
|
|
|
wpa_printf(MSG_INFO, "EAP-TLS: Private key not configured");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
data = os_zalloc(sizeof(*data));
|
|
|
|
if (data == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
2012-04-07 19:57:02 +02:00
|
|
|
data->ssl_ctx = sm->init_phase2 && sm->ssl_ctx2 ? sm->ssl_ctx2 :
|
|
|
|
sm->ssl_ctx;
|
|
|
|
|
2012-08-17 21:26:28 +02:00
|
|
|
if (eap_peer_tls_ssl_init(sm, &data->ssl, config, EAP_TYPE_TLS)) {
|
2008-02-28 02:34:43 +01:00
|
|
|
wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL.");
|
|
|
|
eap_tls_deinit(sm, data);
|
|
|
|
if (config->engine) {
|
|
|
|
wpa_printf(MSG_DEBUG, "EAP-TLS: Requesting Smartcard "
|
|
|
|
"PIN");
|
|
|
|
eap_sm_request_pin(sm);
|
|
|
|
sm->ignore = TRUE;
|
|
|
|
} else if (config->private_key && !config->private_key_passwd)
|
|
|
|
{
|
|
|
|
wpa_printf(MSG_DEBUG, "EAP-TLS: Requesting private "
|
|
|
|
"key passphrase");
|
|
|
|
eap_sm_request_passphrase(sm);
|
|
|
|
sm->ignore = TRUE;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-08-22 21:34:11 +02:00
|
|
|
data->eap_type = EAP_TYPE_TLS;
|
|
|
|
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef EAP_UNAUTH_TLS
|
|
|
|
static void * eap_unauth_tls_init(struct eap_sm *sm)
|
|
|
|
{
|
|
|
|
struct eap_tls_data *data;
|
|
|
|
struct eap_peer_config *config = eap_get_config(sm);
|
|
|
|
|
|
|
|
data = os_zalloc(sizeof(*data));
|
|
|
|
if (data == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
data->ssl_ctx = sm->init_phase2 && sm->ssl_ctx2 ? sm->ssl_ctx2 :
|
|
|
|
sm->ssl_ctx;
|
|
|
|
|
|
|
|
if (eap_peer_tls_ssl_init(sm, &data->ssl, config,
|
|
|
|
EAP_UNAUTH_TLS_TYPE)) {
|
|
|
|
wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL.");
|
|
|
|
eap_tls_deinit(sm, data);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
data->eap_type = EAP_UNAUTH_TLS_TYPE;
|
|
|
|
|
2008-02-28 02:34:43 +01:00
|
|
|
return data;
|
|
|
|
}
|
2012-08-22 21:34:11 +02:00
|
|
|
#endif /* EAP_UNAUTH_TLS */
|
2008-02-28 02:34:43 +01:00
|
|
|
|
|
|
|
|
2013-07-23 20:21:36 +02:00
|
|
|
#ifdef CONFIG_HS20
|
|
|
|
static void * eap_wfa_unauth_tls_init(struct eap_sm *sm)
|
|
|
|
{
|
|
|
|
struct eap_tls_data *data;
|
|
|
|
struct eap_peer_config *config = eap_get_config(sm);
|
|
|
|
|
|
|
|
data = os_zalloc(sizeof(*data));
|
|
|
|
if (data == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
data->ssl_ctx = sm->init_phase2 && sm->ssl_ctx2 ? sm->ssl_ctx2 :
|
|
|
|
sm->ssl_ctx;
|
|
|
|
|
|
|
|
if (eap_peer_tls_ssl_init(sm, &data->ssl, config,
|
|
|
|
EAP_WFA_UNAUTH_TLS_TYPE)) {
|
|
|
|
wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL.");
|
|
|
|
eap_tls_deinit(sm, data);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
data->eap_type = EAP_WFA_UNAUTH_TLS_TYPE;
|
|
|
|
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_HS20 */
|
|
|
|
|
|
|
|
|
2014-06-29 20:16:30 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-28 02:34:43 +01:00
|
|
|
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);
|
2014-06-29 20:16:30 +02:00
|
|
|
eap_tls_free_key(data);
|
2013-02-06 17:52:33 +01:00
|
|
|
os_free(data->session_id);
|
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>
2015-12-12 17:16:54 +01:00
|
|
|
wpabuf_free(data->pending_resp);
|
2008-02-28 02:34:43 +01:00
|
|
|
os_free(data);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static struct wpabuf * eap_tls_failure(struct eap_sm *sm,
|
|
|
|
struct eap_tls_data *data,
|
|
|
|
struct eap_method_ret *ret, int res,
|
|
|
|
struct wpabuf *resp, u8 id)
|
|
|
|
{
|
|
|
|
wpa_printf(MSG_DEBUG, "EAP-TLS: TLS processing failed");
|
|
|
|
|
|
|
|
ret->methodState = METHOD_DONE;
|
|
|
|
ret->decision = DECISION_FAIL;
|
|
|
|
|
|
|
|
if (resp) {
|
|
|
|
/*
|
|
|
|
* This is likely an alert message, so send it instead of just
|
|
|
|
* ACKing the error.
|
|
|
|
*/
|
|
|
|
return resp;
|
|
|
|
}
|
|
|
|
|
2012-08-22 21:34:11 +02:00
|
|
|
return eap_peer_tls_build_ack(id, data->eap_type, 0);
|
2008-02-28 02:34:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data,
|
|
|
|
struct eap_method_ret *ret)
|
|
|
|
{
|
|
|
|
wpa_printf(MSG_DEBUG, "EAP-TLS: Done");
|
|
|
|
|
|
|
|
ret->methodState = METHOD_DONE;
|
|
|
|
ret->decision = DECISION_UNCOND_SUCC;
|
|
|
|
|
2014-06-29 20:16:30 +02:00
|
|
|
eap_tls_free_key(data);
|
2008-02-28 02:34:43 +01:00
|
|
|
data->key_data = eap_peer_tls_derive_key(sm, &data->ssl,
|
|
|
|
"client EAP encryption",
|
|
|
|
EAP_TLS_KEY_LEN +
|
|
|
|
EAP_EMSK_LEN);
|
|
|
|
if (data->key_data) {
|
|
|
|
wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived key",
|
|
|
|
data->key_data, EAP_TLS_KEY_LEN);
|
|
|
|
wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived EMSK",
|
|
|
|
data->key_data + EAP_TLS_KEY_LEN,
|
|
|
|
EAP_EMSK_LEN);
|
|
|
|
} else {
|
|
|
|
wpa_printf(MSG_INFO, "EAP-TLS: Failed to derive key");
|
|
|
|
}
|
2013-02-06 17:52:33 +01:00
|
|
|
|
|
|
|
os_free(data->session_id);
|
|
|
|
data->session_id = eap_peer_tls_derive_session_id(sm, &data->ssl,
|
|
|
|
EAP_TYPE_TLS,
|
|
|
|
&data->id_len);
|
|
|
|
if (data->session_id) {
|
|
|
|
wpa_hexdump(MSG_DEBUG, "EAP-TLS: Derived Session-Id",
|
|
|
|
data->session_id, data->id_len);
|
|
|
|
} else {
|
|
|
|
wpa_printf(MSG_ERROR, "EAP-TLS: Failed to derive Session-Id");
|
|
|
|
}
|
2008-02-28 02:34:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv,
|
|
|
|
struct eap_method_ret *ret,
|
|
|
|
const struct wpabuf *reqData)
|
|
|
|
{
|
|
|
|
size_t left;
|
|
|
|
int res;
|
|
|
|
struct wpabuf *resp;
|
|
|
|
u8 flags, id;
|
|
|
|
const u8 *pos;
|
|
|
|
struct eap_tls_data *data = priv;
|
2015-05-02 15:42:19 +02:00
|
|
|
struct wpabuf msg;
|
2008-02-28 02:34:43 +01: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>
2015-12-12 17:16:54 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2012-08-22 21:34:11 +02:00
|
|
|
pos = eap_peer_tls_process_init(sm, &data->ssl, data->eap_type, ret,
|
2008-02-28 02:34:43 +01:00
|
|
|
reqData, &left, &flags);
|
|
|
|
if (pos == NULL)
|
|
|
|
return NULL;
|
|
|
|
id = eap_get_id(reqData);
|
|
|
|
|
|
|
|
if (flags & EAP_TLS_FLAGS_START) {
|
|
|
|
wpa_printf(MSG_DEBUG, "EAP-TLS: Start");
|
|
|
|
left = 0; /* make sure that this frame is empty, even though it
|
|
|
|
* should always be, anyway */
|
|
|
|
}
|
|
|
|
|
|
|
|
resp = NULL;
|
2015-05-02 15:42:19 +02:00
|
|
|
wpabuf_set(&msg, pos, left);
|
2012-08-22 21:34:11 +02:00
|
|
|
res = eap_peer_tls_process_helper(sm, &data->ssl, data->eap_type, 0,
|
2015-05-02 15:42:19 +02:00
|
|
|
id, &msg, &resp);
|
2008-02-28 02:34:43 +01:00
|
|
|
|
|
|
|
if (res < 0) {
|
|
|
|
return eap_tls_failure(sm, data, ret, res, resp, id);
|
|
|
|
}
|
|
|
|
|
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>
2015-12-12 17:16:54 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2012-04-07 19:57:02 +02:00
|
|
|
if (tls_connection_established(data->ssl_ctx, data->ssl.conn))
|
2008-02-28 02:34:43 +01:00
|
|
|
eap_tls_success(sm, data, ret);
|
|
|
|
|
|
|
|
if (res == 1) {
|
|
|
|
wpabuf_free(resp);
|
2012-08-22 21:34:11 +02:00
|
|
|
return eap_peer_tls_build_ack(id, data->eap_type, 0);
|
2008-02-28 02:34:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return resp;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static Boolean eap_tls_has_reauth_data(struct eap_sm *sm, void *priv)
|
|
|
|
{
|
|
|
|
struct eap_tls_data *data = priv;
|
2012-04-07 19:57:02 +02:00
|
|
|
return tls_connection_established(data->ssl_ctx, data->ssl.conn);
|
2008-02-28 02:34:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void eap_tls_deinit_for_reauth(struct eap_sm *sm, void *priv)
|
|
|
|
{
|
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>
2015-12-12 17:16:54 +01:00
|
|
|
struct eap_tls_data *data = priv;
|
|
|
|
|
|
|
|
wpabuf_free(data->pending_resp);
|
|
|
|
data->pending_resp = NULL;
|
2008-02-28 02:34:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void * eap_tls_init_for_reauth(struct eap_sm *sm, void *priv)
|
|
|
|
{
|
|
|
|
struct eap_tls_data *data = priv;
|
2014-06-29 20:16:30 +02:00
|
|
|
eap_tls_free_key(data);
|
2013-02-06 17:52:33 +01:00
|
|
|
os_free(data->session_id);
|
|
|
|
data->session_id = NULL;
|
2008-02-28 02:34:43 +01:00
|
|
|
if (eap_peer_tls_reauth_init(sm, &data->ssl)) {
|
|
|
|
os_free(data);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return priv;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int eap_tls_get_status(struct eap_sm *sm, void *priv, char *buf,
|
|
|
|
size_t buflen, int verbose)
|
|
|
|
{
|
|
|
|
struct eap_tls_data *data = priv;
|
|
|
|
return eap_peer_tls_status(sm, &data->ssl, buf, buflen, verbose);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static Boolean eap_tls_isKeyAvailable(struct eap_sm *sm, void *priv)
|
|
|
|
{
|
|
|
|
struct eap_tls_data *data = priv;
|
|
|
|
return data->key_data != NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static u8 * eap_tls_getKey(struct eap_sm *sm, void *priv, size_t *len)
|
|
|
|
{
|
|
|
|
struct eap_tls_data *data = priv;
|
|
|
|
u8 *key;
|
|
|
|
|
|
|
|
if (data->key_data == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
key = os_malloc(EAP_TLS_KEY_LEN);
|
|
|
|
if (key == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
*len = EAP_TLS_KEY_LEN;
|
|
|
|
os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN);
|
|
|
|
|
|
|
|
return key;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static u8 * eap_tls_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
|
|
|
|
{
|
|
|
|
struct eap_tls_data *data = priv;
|
|
|
|
u8 *key;
|
|
|
|
|
|
|
|
if (data->key_data == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
key = os_malloc(EAP_EMSK_LEN);
|
|
|
|
if (key == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
*len = EAP_EMSK_LEN;
|
|
|
|
os_memcpy(key, data->key_data + EAP_TLS_KEY_LEN, EAP_EMSK_LEN);
|
|
|
|
|
|
|
|
return key;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-02-06 17:52:33 +01:00
|
|
|
static u8 * eap_tls_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
|
|
|
|
{
|
|
|
|
struct eap_tls_data *data = priv;
|
|
|
|
u8 *id;
|
|
|
|
|
|
|
|
if (data->session_id == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
id = os_malloc(data->id_len);
|
|
|
|
if (id == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
*len = data->id_len;
|
|
|
|
os_memcpy(id, data->session_id, data->id_len);
|
|
|
|
|
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-28 02:34:43 +01:00
|
|
|
int eap_peer_tls_register(void)
|
|
|
|
{
|
|
|
|
struct eap_method *eap;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
|
|
|
|
EAP_VENDOR_IETF, EAP_TYPE_TLS, "TLS");
|
|
|
|
if (eap == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
eap->init = eap_tls_init;
|
|
|
|
eap->deinit = eap_tls_deinit;
|
|
|
|
eap->process = eap_tls_process;
|
|
|
|
eap->isKeyAvailable = eap_tls_isKeyAvailable;
|
|
|
|
eap->getKey = eap_tls_getKey;
|
2013-02-06 17:52:33 +01:00
|
|
|
eap->getSessionId = eap_tls_get_session_id;
|
2008-02-28 02:34:43 +01:00
|
|
|
eap->get_status = eap_tls_get_status;
|
|
|
|
eap->has_reauth_data = eap_tls_has_reauth_data;
|
|
|
|
eap->deinit_for_reauth = eap_tls_deinit_for_reauth;
|
|
|
|
eap->init_for_reauth = eap_tls_init_for_reauth;
|
|
|
|
eap->get_emsk = eap_tls_get_emsk;
|
|
|
|
|
|
|
|
ret = eap_peer_method_register(eap);
|
|
|
|
if (ret)
|
|
|
|
eap_peer_method_free(eap);
|
|
|
|
return ret;
|
|
|
|
}
|
2012-08-22 21:34:11 +02:00
|
|
|
|
|
|
|
|
|
|
|
#ifdef EAP_UNAUTH_TLS
|
|
|
|
int eap_peer_unauth_tls_register(void)
|
|
|
|
{
|
|
|
|
struct eap_method *eap;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
|
|
|
|
EAP_VENDOR_UNAUTH_TLS,
|
|
|
|
EAP_VENDOR_TYPE_UNAUTH_TLS, "UNAUTH-TLS");
|
|
|
|
if (eap == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
eap->init = eap_unauth_tls_init;
|
|
|
|
eap->deinit = eap_tls_deinit;
|
|
|
|
eap->process = eap_tls_process;
|
|
|
|
eap->isKeyAvailable = eap_tls_isKeyAvailable;
|
|
|
|
eap->getKey = eap_tls_getKey;
|
|
|
|
eap->get_status = eap_tls_get_status;
|
|
|
|
eap->has_reauth_data = eap_tls_has_reauth_data;
|
|
|
|
eap->deinit_for_reauth = eap_tls_deinit_for_reauth;
|
|
|
|
eap->init_for_reauth = eap_tls_init_for_reauth;
|
|
|
|
eap->get_emsk = eap_tls_get_emsk;
|
|
|
|
|
|
|
|
ret = eap_peer_method_register(eap);
|
|
|
|
if (ret)
|
|
|
|
eap_peer_method_free(eap);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
#endif /* EAP_UNAUTH_TLS */
|
2013-07-23 20:21:36 +02:00
|
|
|
|
|
|
|
|
|
|
|
#ifdef CONFIG_HS20
|
|
|
|
int eap_peer_wfa_unauth_tls_register(void)
|
|
|
|
{
|
|
|
|
struct eap_method *eap;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
|
|
|
|
EAP_VENDOR_WFA_NEW,
|
|
|
|
EAP_VENDOR_WFA_UNAUTH_TLS,
|
|
|
|
"WFA-UNAUTH-TLS");
|
|
|
|
if (eap == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
eap->init = eap_wfa_unauth_tls_init;
|
|
|
|
eap->deinit = eap_tls_deinit;
|
|
|
|
eap->process = eap_tls_process;
|
|
|
|
eap->isKeyAvailable = eap_tls_isKeyAvailable;
|
|
|
|
eap->getKey = eap_tls_getKey;
|
|
|
|
eap->get_status = eap_tls_get_status;
|
|
|
|
eap->has_reauth_data = eap_tls_has_reauth_data;
|
|
|
|
eap->deinit_for_reauth = eap_tls_deinit_for_reauth;
|
|
|
|
eap->init_for_reauth = eap_tls_init_for_reauth;
|
|
|
|
eap->get_emsk = eap_tls_get_emsk;
|
|
|
|
|
|
|
|
ret = eap_peer_method_register(eap);
|
|
|
|
if (ret)
|
|
|
|
eap_peer_method_free(eap);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_HS20 */
|