mirror of
https://github.com/vanhoefm/fragattacks.git
synced 2024-11-25 00:38:24 -05:00
Remove EAP-TTLSv1 and TLS/IA
These protocols seem to be abandoned: latest IETF drafts have expired years ago and it does not seem likely that EAP-TTLSv1 would be deployed. The implementation in hostapd/wpa_supplicant was not complete and not fully tested. In addition, the TLS/IA functionality was only available when GnuTLS was used. Since GnuTLS removed this functionality in 3.0.0, there is no available TLS/IA implementation in the latest version of any supported TLS library. Remove the EAP-TTLSv1 and TLS/IA implementation to clean up unwanted complexity from hostapd and wpa_supplicant. In addition, this removes any potential use of the GnuTLS extra library.
This commit is contained in:
parent
e655e1f512
commit
fd2f2d0489
@ -456,10 +456,6 @@ ifeq ($(CONFIG_TLS), gnutls)
|
||||
ifdef TLS_FUNCS
|
||||
OBJS += ../src/crypto/tls_gnutls.o
|
||||
LIBS += -lgnutls -lgpg-error
|
||||
ifdef CONFIG_GNUTLS_EXTRA
|
||||
CFLAGS += -DCONFIG_GNUTLS_EXTRA
|
||||
LIBS += -lgnutls-extra
|
||||
endif
|
||||
endif
|
||||
OBJS += ../src/crypto/crypto_gnutls.o
|
||||
HOBJS += ../src/crypto/crypto_gnutls.o
|
||||
|
@ -211,19 +211,11 @@ CONFIG_IPV6=y
|
||||
|
||||
# Select TLS implementation
|
||||
# openssl = OpenSSL (default)
|
||||
# gnutls = GnuTLS (needed for TLS/IA, see also CONFIG_GNUTLS_EXTRA)
|
||||
# gnutls = GnuTLS
|
||||
# internal = Internal TLSv1 implementation (experimental)
|
||||
# none = Empty template
|
||||
#CONFIG_TLS=openssl
|
||||
|
||||
# Whether to enable TLS/IA support, which is required for EAP-TTLSv1.
|
||||
# You need CONFIG_TLS=gnutls for this to have any effect. Please note that
|
||||
# even though the core GnuTLS library is released under LGPL, this extra
|
||||
# library uses GPL and as such, the terms of GPL apply to the combination
|
||||
# of wpa_supplicant and GnuTLS if this option is enabled. BSD license may not
|
||||
# apply for distribution of the resulting binary.
|
||||
#CONFIG_GNUTLS_EXTRA=y
|
||||
|
||||
# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.1)
|
||||
# can be enabled to get a stronger construction of messages when block ciphers
|
||||
# are used.
|
||||
|
@ -24,8 +24,6 @@ struct tls_keys {
|
||||
size_t client_random_len;
|
||||
const u8 *server_random;
|
||||
size_t server_random_len;
|
||||
const u8 *inner_secret; /* TLS/IA inner secret */
|
||||
size_t inner_secret_len;
|
||||
};
|
||||
|
||||
enum tls_event {
|
||||
@ -115,7 +113,6 @@ struct tls_config {
|
||||
* specific for now)
|
||||
* @cert_id: the certificate's id when using engine
|
||||
* @ca_cert_id: the CA certificate's id when using engine
|
||||
* @tls_ia: Whether to enable TLS/IA (for EAP-TTLSv1)
|
||||
* @flags: Parameter options (TLS_CONN_*)
|
||||
*
|
||||
* TLS connection parameters to be configured with tls_connection_set_params()
|
||||
@ -143,7 +140,6 @@ struct tls_connection_params {
|
||||
const char *dh_file;
|
||||
const u8 *dh_blob;
|
||||
size_t dh_blob_len;
|
||||
int tls_ia;
|
||||
|
||||
/* OpenSSL specific variables */
|
||||
int engine;
|
||||
@ -282,20 +278,6 @@ int __must_check tls_connection_set_verify(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
int verify_peer);
|
||||
|
||||
/**
|
||||
* tls_connection_set_ia - Set TLS/IA parameters
|
||||
* @tls_ctx: TLS context data from tls_init()
|
||||
* @conn: Connection context data from tls_connection_init()
|
||||
* @tls_ia: 1 = enable TLS/IA
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* This function is used to configure TLS/IA in server mode where
|
||||
* tls_connection_set_params() is not used.
|
||||
*/
|
||||
int __must_check tls_connection_set_ia(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
int tls_ia);
|
||||
|
||||
/**
|
||||
* tls_connection_get_keys - Get master key and random data from TLS connection
|
||||
* @tls_ctx: TLS context data from tls_init()
|
||||
@ -515,7 +497,6 @@ int tls_connection_get_write_alerts(void *tls_ctx,
|
||||
int tls_connection_get_keyblock_size(void *tls_ctx,
|
||||
struct tls_connection *conn);
|
||||
|
||||
#define TLS_CAPABILITY_IA 0x0001 /* TLS Inner Application (TLS/IA) */
|
||||
/**
|
||||
* tls_capabilities - Get supported TLS capabilities
|
||||
* @tls_ctx: TLS context data from tls_init()
|
||||
@ -523,42 +504,6 @@ int tls_connection_get_keyblock_size(void *tls_ctx,
|
||||
*/
|
||||
unsigned int tls_capabilities(void *tls_ctx);
|
||||
|
||||
/**
|
||||
* tls_connection_ia_send_phase_finished - Send a TLS/IA PhaseFinished message
|
||||
* @tls_ctx: TLS context data from tls_init()
|
||||
* @conn: Connection context data from tls_connection_init()
|
||||
* @final: 1 = FinalPhaseFinished, 0 = IntermediatePhaseFinished
|
||||
* Returns: Encrypted TLS/IA data, %NULL on failure
|
||||
*
|
||||
* This function is used to send the TLS/IA end phase message, e.g., when the
|
||||
* EAP server completes EAP-TTLSv1.
|
||||
*/
|
||||
struct wpabuf * tls_connection_ia_send_phase_finished(
|
||||
void *tls_ctx, struct tls_connection *conn, int final);
|
||||
|
||||
/**
|
||||
* tls_connection_ia_final_phase_finished - Has final phase been completed
|
||||
* @tls_ctx: TLS context data from tls_init()
|
||||
* @conn: Connection context data from tls_connection_init()
|
||||
* Returns: 1 if valid FinalPhaseFinished has been received, 0 if not, or -1
|
||||
* on failure
|
||||
*/
|
||||
int __must_check tls_connection_ia_final_phase_finished(
|
||||
void *tls_ctx, struct tls_connection *conn);
|
||||
|
||||
/**
|
||||
* tls_connection_ia_permute_inner_secret - Permute TLS/IA inner secret
|
||||
* @tls_ctx: TLS context data from tls_init()
|
||||
* @conn: Connection context data from tls_connection_init()
|
||||
* @key: Session key material (session_key vectors with 2-octet length), or
|
||||
* %NULL if no session key was generating in the current phase
|
||||
* @key_len: Length of session key material
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int __must_check tls_connection_ia_permute_inner_secret(
|
||||
void *tls_ctx, struct tls_connection *conn,
|
||||
const u8 *key, size_t key_len);
|
||||
|
||||
typedef int (*tls_session_ticket_cb)
|
||||
(void *ctx, const u8 *ticket, size_t len, const u8 *client_random,
|
||||
const u8 *server_random, u8 *master_secret);
|
||||
|
@ -19,18 +19,6 @@
|
||||
#include <gnutls/pkcs12.h>
|
||||
#endif /* PKCS12_FUNCS */
|
||||
|
||||
#ifdef CONFIG_GNUTLS_EXTRA
|
||||
#if LIBGNUTLS_VERSION_NUMBER >= 0x010302
|
||||
#define GNUTLS_IA
|
||||
#include <gnutls/extra.h>
|
||||
#if LIBGNUTLS_VERSION_NUMBER == 0x010302
|
||||
/* This function is not included in the current gnutls/extra.h even though it
|
||||
* should be, so define it here as a workaround for the time being. */
|
||||
int gnutls_ia_verify_endphase(gnutls_session_t session, char *checksum);
|
||||
#endif /* LIBGNUTLS_VERSION_NUMBER == 0x010302 */
|
||||
#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
|
||||
#endif /* CONFIG_GNUTLS_EXTRA */
|
||||
|
||||
#include "common.h"
|
||||
#include "tls.h"
|
||||
|
||||
@ -114,21 +102,6 @@ struct tls_connection {
|
||||
|
||||
int params_set;
|
||||
gnutls_certificate_credentials_t xcred;
|
||||
|
||||
int tls_ia;
|
||||
int final_phase_finished;
|
||||
|
||||
#ifdef GNUTLS_IA
|
||||
gnutls_ia_server_credentials_t iacred_srv;
|
||||
gnutls_ia_client_credentials_t iacred_cli;
|
||||
|
||||
/* Session keys generated in the current phase for inner secret
|
||||
* permutation before generating/verifying PhaseFinished. */
|
||||
u8 *session_keys;
|
||||
size_t session_keys_len;
|
||||
|
||||
u8 inner_secret[WPA_TLS_MASTER_SIZE];
|
||||
#endif /* GNUTLS_IA */
|
||||
};
|
||||
|
||||
|
||||
@ -374,17 +347,6 @@ void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn)
|
||||
if (conn == NULL)
|
||||
return;
|
||||
|
||||
#ifdef GNUTLS_IA
|
||||
if (conn->iacred_srv)
|
||||
gnutls_ia_free_server_credentials(conn->iacred_srv);
|
||||
if (conn->iacred_cli)
|
||||
gnutls_ia_free_client_credentials(conn->iacred_cli);
|
||||
if (conn->session_keys) {
|
||||
os_memset(conn->session_keys, 0, conn->session_keys_len);
|
||||
os_free(conn->session_keys);
|
||||
}
|
||||
#endif /* GNUTLS_IA */
|
||||
|
||||
gnutls_certificate_free_credentials(conn->xcred);
|
||||
gnutls_deinit(conn->session);
|
||||
os_free(conn->pre_shared_secret);
|
||||
@ -417,14 +379,6 @@ int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
|
||||
wpabuf_free(conn->push_buf);
|
||||
conn->push_buf = NULL;
|
||||
conn->established = 0;
|
||||
conn->final_phase_finished = 0;
|
||||
#ifdef GNUTLS_IA
|
||||
if (conn->session_keys) {
|
||||
os_memset(conn->session_keys, 0, conn->session_keys_len);
|
||||
os_free(conn->session_keys);
|
||||
}
|
||||
conn->session_keys_len = 0;
|
||||
#endif /* GNUTLS_IA */
|
||||
|
||||
gnutls_deinit(conn->session);
|
||||
if (tls_gnutls_init_session(global, conn)) {
|
||||
@ -658,7 +612,6 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
|
||||
}
|
||||
}
|
||||
|
||||
conn->tls_ia = params->tls_ia;
|
||||
conn->params_set = 1;
|
||||
|
||||
ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE,
|
||||
@ -668,28 +621,6 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
|
||||
gnutls_strerror(ret));
|
||||
}
|
||||
|
||||
#ifdef GNUTLS_IA
|
||||
if (conn->iacred_cli)
|
||||
gnutls_ia_free_client_credentials(conn->iacred_cli);
|
||||
|
||||
ret = gnutls_ia_allocate_client_credentials(&conn->iacred_cli);
|
||||
if (ret) {
|
||||
wpa_printf(MSG_DEBUG, "Failed to allocate IA credentials: %s",
|
||||
gnutls_strerror(ret));
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_IA,
|
||||
conn->iacred_cli);
|
||||
if (ret) {
|
||||
wpa_printf(MSG_DEBUG, "Failed to configure IA credentials: %s",
|
||||
gnutls_strerror(ret));
|
||||
gnutls_ia_free_client_credentials(conn->iacred_cli);
|
||||
conn->iacred_cli = NULL;
|
||||
return -1;
|
||||
}
|
||||
#endif /* GNUTLS_IE */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -852,13 +783,6 @@ int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn,
|
||||
#endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */
|
||||
#endif /* LIBGNUTLS_VERSION_NUMBER < 0x020c00 */
|
||||
|
||||
#ifdef GNUTLS_IA
|
||||
gnutls_ia_extract_inner_secret(conn->session,
|
||||
(char *) conn->inner_secret);
|
||||
keys->inner_secret = conn->inner_secret;
|
||||
keys->inner_secret_len = WPA_TLS_MASTER_SIZE;
|
||||
#endif /* GNUTLS_IA */
|
||||
|
||||
#if LIBGNUTLS_VERSION_NUMBER < 0x020c00
|
||||
keys->client_random_len = WPA_TLS_RANDOM_SIZE;
|
||||
keys->server_random_len = WPA_TLS_RANDOM_SIZE;
|
||||
@ -1009,7 +933,7 @@ static struct wpabuf * gnutls_get_appl_data(struct tls_connection *conn)
|
||||
wpabuf_size(ad));
|
||||
wpa_printf(MSG_DEBUG, "GnuTLS: gnutls_record_recv: %d", res);
|
||||
if (res < 0) {
|
||||
wpa_printf(MSG_DEBUG, "%s - gnutls_ia_recv failed: %d "
|
||||
wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d "
|
||||
"(%s)", __func__, (int) res,
|
||||
gnutls_strerror(res));
|
||||
wpabuf_free(ad);
|
||||
@ -1083,20 +1007,7 @@ struct wpabuf * tls_connection_handshake(void *tls_ctx,
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_GNUTLS_EXTRA
|
||||
if (conn->tls_ia && !gnutls_ia_handshake_p(conn->session)) {
|
||||
wpa_printf(MSG_INFO, "TLS: No TLS/IA negotiation");
|
||||
conn->failed++;
|
||||
return NULL;
|
||||
}
|
||||
#endif /* CONFIG_GNUTLS_EXTRA */
|
||||
|
||||
if (conn->tls_ia)
|
||||
wpa_printf(MSG_DEBUG, "TLS: Start TLS/IA handshake");
|
||||
else {
|
||||
wpa_printf(MSG_DEBUG, "TLS: Handshake completed "
|
||||
"successfully");
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "TLS: Handshake completed successfully");
|
||||
conn->established = 1;
|
||||
if (conn->push_buf == NULL) {
|
||||
/* Need to return something to get final TLS ACK. */
|
||||
@ -1143,12 +1054,6 @@ struct wpabuf * tls_connection_encrypt(void *tls_ctx,
|
||||
ssize_t res;
|
||||
struct wpabuf *buf;
|
||||
|
||||
#ifdef GNUTLS_IA
|
||||
if (conn->tls_ia)
|
||||
res = gnutls_ia_send(conn->session, wpabuf_head(in_data),
|
||||
wpabuf_len(in_data));
|
||||
else
|
||||
#endif /* GNUTLS_IA */
|
||||
res = gnutls_record_send(conn->session, wpabuf_head(in_data),
|
||||
wpabuf_len(in_data));
|
||||
if (res < 0) {
|
||||
@ -1191,65 +1096,6 @@ struct wpabuf * tls_connection_decrypt(void *tls_ctx,
|
||||
if (out == NULL)
|
||||
return NULL;
|
||||
|
||||
#ifdef GNUTLS_IA
|
||||
if (conn->tls_ia) {
|
||||
res = gnutls_ia_recv(conn->session, wpabuf_mhead(out),
|
||||
wpabuf_size(out));
|
||||
if (res == GNUTLS_E_WARNING_IA_IPHF_RECEIVED ||
|
||||
res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED) {
|
||||
int final = res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED;
|
||||
wpa_printf(MSG_DEBUG, "%s: Received %sPhaseFinished",
|
||||
__func__, final ? "Final" : "Intermediate");
|
||||
|
||||
res = gnutls_ia_permute_inner_secret(
|
||||
conn->session, conn->session_keys_len,
|
||||
(char *) conn->session_keys);
|
||||
if (conn->session_keys) {
|
||||
os_memset(conn->session_keys, 0,
|
||||
conn->session_keys_len);
|
||||
os_free(conn->session_keys);
|
||||
}
|
||||
conn->session_keys = NULL;
|
||||
conn->session_keys_len = 0;
|
||||
if (res) {
|
||||
wpa_printf(MSG_DEBUG, "%s: Failed to permute "
|
||||
"inner secret: %s",
|
||||
__func__, gnutls_strerror(res));
|
||||
wpabuf_free(out);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
res = gnutls_ia_verify_endphase(conn->session,
|
||||
wpabuf_head(out));
|
||||
if (res == 0) {
|
||||
wpa_printf(MSG_DEBUG, "%s: Correct endphase "
|
||||
"checksum", __func__);
|
||||
} else {
|
||||
wpa_printf(MSG_INFO, "%s: Endphase "
|
||||
"verification failed: %s",
|
||||
__func__, gnutls_strerror(res));
|
||||
wpabuf_free(out);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (final)
|
||||
conn->final_phase_finished = 1;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
if (res < 0) {
|
||||
wpa_printf(MSG_DEBUG, "%s - gnutls_ia_recv failed: %d "
|
||||
"(%s)", __func__, (int) res,
|
||||
gnutls_strerror(res));
|
||||
wpabuf_free(out);
|
||||
return NULL;
|
||||
}
|
||||
wpabuf_put(out, res);
|
||||
return out;
|
||||
}
|
||||
#endif /* GNUTLS_IA */
|
||||
|
||||
res = gnutls_record_recv(conn->session, wpabuf_mhead(out),
|
||||
wpabuf_size(out));
|
||||
if (res < 0) {
|
||||
@ -1340,133 +1186,7 @@ int tls_connection_get_keyblock_size(void *tls_ctx,
|
||||
|
||||
unsigned int tls_capabilities(void *tls_ctx)
|
||||
{
|
||||
unsigned int capa = 0;
|
||||
|
||||
#ifdef GNUTLS_IA
|
||||
capa |= TLS_CAPABILITY_IA;
|
||||
#endif /* GNUTLS_IA */
|
||||
|
||||
return capa;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
|
||||
int tls_ia)
|
||||
{
|
||||
#ifdef GNUTLS_IA
|
||||
int ret;
|
||||
|
||||
if (conn == NULL)
|
||||
return -1;
|
||||
|
||||
conn->tls_ia = tls_ia;
|
||||
if (!tls_ia)
|
||||
return 0;
|
||||
|
||||
ret = gnutls_ia_allocate_server_credentials(&conn->iacred_srv);
|
||||
if (ret) {
|
||||
wpa_printf(MSG_DEBUG, "Failed to allocate IA credentials: %s",
|
||||
gnutls_strerror(ret));
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_IA,
|
||||
conn->iacred_srv);
|
||||
if (ret) {
|
||||
wpa_printf(MSG_DEBUG, "Failed to configure IA credentials: %s",
|
||||
gnutls_strerror(ret));
|
||||
gnutls_ia_free_server_credentials(conn->iacred_srv);
|
||||
conn->iacred_srv = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
#else /* GNUTLS_IA */
|
||||
return -1;
|
||||
#endif /* GNUTLS_IA */
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * tls_connection_ia_send_phase_finished(
|
||||
void *tls_ctx, struct tls_connection *conn, int final)
|
||||
{
|
||||
#ifdef GNUTLS_IA
|
||||
int ret;
|
||||
struct wpabuf *buf;
|
||||
|
||||
if (conn == NULL || conn->session == NULL || !conn->tls_ia)
|
||||
return NULL;
|
||||
|
||||
ret = gnutls_ia_permute_inner_secret(conn->session,
|
||||
conn->session_keys_len,
|
||||
(char *) conn->session_keys);
|
||||
if (conn->session_keys) {
|
||||
os_memset(conn->session_keys, 0, conn->session_keys_len);
|
||||
os_free(conn->session_keys);
|
||||
}
|
||||
conn->session_keys = NULL;
|
||||
conn->session_keys_len = 0;
|
||||
if (ret) {
|
||||
wpa_printf(MSG_DEBUG, "%s: Failed to permute inner secret: %s",
|
||||
__func__, gnutls_strerror(ret));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = gnutls_ia_endphase_send(conn->session, final);
|
||||
if (ret) {
|
||||
wpa_printf(MSG_DEBUG, "%s: Failed to send endphase: %s",
|
||||
__func__, gnutls_strerror(ret));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buf = conn->push_buf;
|
||||
conn->push_buf = NULL;
|
||||
return buf;
|
||||
#else /* GNUTLS_IA */
|
||||
return NULL;
|
||||
#endif /* GNUTLS_IA */
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_ia_final_phase_finished(void *tls_ctx,
|
||||
struct tls_connection *conn)
|
||||
{
|
||||
if (conn == NULL)
|
||||
return -1;
|
||||
|
||||
return conn->final_phase_finished;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_ia_permute_inner_secret(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
const u8 *key, size_t key_len)
|
||||
{
|
||||
#ifdef GNUTLS_IA
|
||||
if (conn == NULL || !conn->tls_ia)
|
||||
return -1;
|
||||
|
||||
if (conn->session_keys) {
|
||||
os_memset(conn->session_keys, 0, conn->session_keys_len);
|
||||
os_free(conn->session_keys);
|
||||
}
|
||||
conn->session_keys_len = 0;
|
||||
|
||||
if (key) {
|
||||
conn->session_keys = os_malloc(key_len);
|
||||
if (conn->session_keys == NULL)
|
||||
return -1;
|
||||
os_memcpy(conn->session_keys, key, key_len);
|
||||
conn->session_keys_len = key_len;
|
||||
} else {
|
||||
conn->session_keys = NULL;
|
||||
conn->session_keys_len = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
#else /* GNUTLS_IA */
|
||||
return -1;
|
||||
#endif /* GNUTLS_IA */
|
||||
}
|
||||
|
||||
|
||||
|
@ -290,13 +290,6 @@ int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn,
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
|
||||
int tls_ia)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn,
|
||||
struct tls_keys *keys)
|
||||
{
|
||||
@ -611,28 +604,6 @@ unsigned int tls_capabilities(void *tls_ctx)
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * tls_connection_ia_send_phase_finished(
|
||||
void *tls_ctx, struct tls_connection *conn, int final)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_ia_final_phase_finished(void *tls_ctx,
|
||||
struct tls_connection *conn)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_ia_permute_inner_secret(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
const u8 *key, size_t key_len)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_set_session_ticket_cb(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
tls_session_ticket_cb cb,
|
||||
|
@ -84,13 +84,6 @@ int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn,
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
|
||||
int tls_ia)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn,
|
||||
struct tls_keys *keys)
|
||||
{
|
||||
@ -205,25 +198,3 @@ unsigned int tls_capabilities(void *tls_ctx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * tls_connection_ia_send_phase_finished(
|
||||
void *tls_ctx, struct tls_connection *conn, int final)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_ia_final_phase_finished(void *tls_ctx,
|
||||
struct tls_connection *conn)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_ia_permute_inner_secret(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
const u8 *key, size_t key_len)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
@ -419,13 +419,6 @@ int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn,
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
|
||||
int tls_ia)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn,
|
||||
struct tls_keys *keys)
|
||||
{
|
||||
@ -649,28 +642,6 @@ unsigned int tls_capabilities(void *tls_ctx)
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * tls_connection_ia_send_phase_finished(
|
||||
void *tls_ctx, struct tls_connection *conn, int final)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_ia_final_phase_finished(void *tls_ctx,
|
||||
struct tls_connection *conn)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_ia_permute_inner_secret(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
const u8 *key, size_t key_len)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_set_session_ticket_cb(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
tls_session_ticket_cb cb,
|
||||
|
@ -2811,35 +2811,6 @@ unsigned int tls_capabilities(void *tls_ctx)
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
|
||||
int tls_ia)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * tls_connection_ia_send_phase_finished(
|
||||
void *tls_ctx, struct tls_connection *conn, int final)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_ia_final_phase_finished(void *tls_ctx,
|
||||
struct tls_connection *conn)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_ia_permute_inner_secret(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
const u8 *key, size_t key_len)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST)
|
||||
/* Pre-shared secred requires a patch to openssl, so this function is
|
||||
* commented out unless explicitly needed for EAP-FAST in order to be able to
|
||||
|
@ -736,32 +736,3 @@ unsigned int tls_capabilities(void *tls_ctx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
|
||||
int tls_ia)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * tls_connection_ia_send_phase_finished(
|
||||
void *tls_ctx, struct tls_connection *conn, int final);
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_ia_final_phase_finished(void *tls_ctx,
|
||||
struct tls_connection *conn)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_ia_permute_inner_secret(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
const u8 *key, size_t key_len)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
@ -112,7 +112,6 @@ static int eap_tls_params_from_conf(struct eap_sm *sm,
|
||||
wpa_printf(MSG_DEBUG, "TLS: using phase1 config options");
|
||||
eap_tls_params_from_conf1(params, config);
|
||||
}
|
||||
params->tls_ia = data->tls_ia;
|
||||
|
||||
/*
|
||||
* Use blob data, if available. Otherwise, leave reference to external
|
||||
|
@ -65,11 +65,6 @@ struct eap_ssl_data {
|
||||
*/
|
||||
int include_tls_length;
|
||||
|
||||
/**
|
||||
* tls_ia - Whether TLS/IA is enabled for this TLS connection
|
||||
*/
|
||||
int tls_ia;
|
||||
|
||||
/**
|
||||
* eap - EAP state machine allocated with eap_peer_sm_init()
|
||||
*/
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* EAP peer method: EAP-TTLS (RFC 5281)
|
||||
* Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2004-2011, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@ -26,17 +26,7 @@
|
||||
#include "eap_config.h"
|
||||
|
||||
|
||||
/* Maximum supported TTLS version
|
||||
* 0 = RFC 5281
|
||||
* 1 = draft-funk-eap-ttls-v1-00.txt
|
||||
*/
|
||||
#ifndef EAP_TTLS_VERSION
|
||||
#define EAP_TTLS_VERSION 0 /* TTLSv1 implementation is not yet complete */
|
||||
#endif /* EAP_TTLS_VERSION */
|
||||
|
||||
|
||||
#define MSCHAPV2_KEY_LEN 16
|
||||
#define MSCHAPV2_NT_RESPONSE_LEN 24
|
||||
#define EAP_TTLS_VERSION 0
|
||||
|
||||
|
||||
static void eap_ttls_deinit(struct eap_sm *sm, void *priv);
|
||||
@ -44,9 +34,8 @@ static void eap_ttls_deinit(struct eap_sm *sm, void *priv);
|
||||
|
||||
struct eap_ttls_data {
|
||||
struct eap_ssl_data ssl;
|
||||
int ssl_initialized;
|
||||
|
||||
int ttls_version, force_ttls_version;
|
||||
int ttls_version;
|
||||
|
||||
const struct eap_method *phase2_method;
|
||||
void *phase2_priv;
|
||||
@ -91,22 +80,9 @@ static void * eap_ttls_init(struct eap_sm *sm)
|
||||
if (data == NULL)
|
||||
return NULL;
|
||||
data->ttls_version = EAP_TTLS_VERSION;
|
||||
data->force_ttls_version = -1;
|
||||
selected = "EAP";
|
||||
data->phase2_type = EAP_TTLS_PHASE2_EAP;
|
||||
|
||||
#if EAP_TTLS_VERSION > 0
|
||||
if (config && config->phase1) {
|
||||
const char *pos = os_strstr(config->phase1, "ttlsver=");
|
||||
if (pos) {
|
||||
data->force_ttls_version = atoi(pos + 8);
|
||||
data->ttls_version = data->force_ttls_version;
|
||||
wpa_printf(MSG_DEBUG, "EAP-TTLS: Forced TTLS version "
|
||||
"%d", data->force_ttls_version);
|
||||
}
|
||||
}
|
||||
#endif /* EAP_TTLS_VERSION */
|
||||
|
||||
if (config && config->phase2) {
|
||||
if (os_strstr(config->phase2, "autheap=")) {
|
||||
selected = "EAP";
|
||||
@ -140,19 +116,11 @@ static void * eap_ttls_init(struct eap_sm *sm)
|
||||
data->phase2_eap_type.method = EAP_TYPE_NONE;
|
||||
}
|
||||
|
||||
#if EAP_TTLS_VERSION > 0
|
||||
if (!(tls_capabilities(sm->ssl_ctx) & TLS_CAPABILITY_IA) &&
|
||||
data->ttls_version > 0) {
|
||||
if (data->force_ttls_version > 0) {
|
||||
wpa_printf(MSG_INFO, "EAP-TTLS: Forced TTLSv%d and "
|
||||
"TLS library does not support TLS/IA.",
|
||||
data->force_ttls_version);
|
||||
if (eap_peer_tls_ssl_init(sm, &data->ssl, config)) {
|
||||
wpa_printf(MSG_INFO, "EAP-TTLS: Failed to initialize SSL.");
|
||||
eap_ttls_deinit(sm, data);
|
||||
return NULL;
|
||||
}
|
||||
data->ttls_version = 0;
|
||||
}
|
||||
#endif /* EAP_TTLS_VERSION */
|
||||
|
||||
return data;
|
||||
}
|
||||
@ -176,7 +144,6 @@ static void eap_ttls_deinit(struct eap_sm *sm, void *priv)
|
||||
return;
|
||||
eap_ttls_phase2_eap_deinit(sm, data);
|
||||
os_free(data->phase2_eap_types);
|
||||
if (data->ssl_initialized)
|
||||
eap_peer_tls_ssl_deinit(sm, &data->ssl);
|
||||
os_free(data->key_data);
|
||||
wpabuf_free(data->pending_phase2_req);
|
||||
@ -246,39 +213,6 @@ static int eap_ttls_avp_encapsulate(struct wpabuf **resp, u32 avp_code,
|
||||
}
|
||||
|
||||
|
||||
#if EAP_TTLS_VERSION > 0
|
||||
static int eap_ttls_ia_permute_inner_secret(struct eap_sm *sm,
|
||||
struct eap_ttls_data *data,
|
||||
const u8 *key, size_t key_len)
|
||||
{
|
||||
u8 *buf;
|
||||
size_t buf_len;
|
||||
int ret;
|
||||
|
||||
if (key) {
|
||||
buf_len = 2 + key_len;
|
||||
buf = os_malloc(buf_len);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
WPA_PUT_BE16(buf, key_len);
|
||||
os_memcpy(buf + 2, key, key_len);
|
||||
} else {
|
||||
buf = NULL;
|
||||
buf_len = 0;
|
||||
}
|
||||
|
||||
wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Session keys for TLS/IA inner "
|
||||
"secret permutation", buf, buf_len);
|
||||
ret = tls_connection_ia_permute_inner_secret(sm->ssl_ctx,
|
||||
data->ssl.conn,
|
||||
buf, buf_len);
|
||||
os_free(buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* EAP_TTLS_VERSION */
|
||||
|
||||
|
||||
static int eap_ttls_v0_derive_key(struct eap_sm *sm,
|
||||
struct eap_ttls_data *data)
|
||||
{
|
||||
@ -298,156 +232,10 @@ static int eap_ttls_v0_derive_key(struct eap_sm *sm,
|
||||
}
|
||||
|
||||
|
||||
#if EAP_TTLS_VERSION > 0
|
||||
static int eap_ttls_v1_derive_key(struct eap_sm *sm,
|
||||
struct eap_ttls_data *data)
|
||||
{
|
||||
struct tls_keys keys;
|
||||
u8 *rnd;
|
||||
|
||||
os_free(data->key_data);
|
||||
data->key_data = NULL;
|
||||
|
||||
os_memset(&keys, 0, sizeof(keys));
|
||||
if (tls_connection_get_keys(sm->ssl_ctx, data->ssl.conn, &keys) ||
|
||||
keys.client_random == NULL || keys.server_random == NULL ||
|
||||
keys.inner_secret == NULL) {
|
||||
wpa_printf(MSG_INFO, "EAP-TTLS: Could not get inner secret, "
|
||||
"client random, or server random to derive keying "
|
||||
"material");
|
||||
return -1;
|
||||
}
|
||||
|
||||
rnd = os_malloc(keys.client_random_len + keys.server_random_len);
|
||||
data->key_data = os_malloc(EAP_TLS_KEY_LEN);
|
||||
if (rnd == NULL || data->key_data == NULL) {
|
||||
wpa_printf(MSG_INFO, "EAP-TTLS: No memory for key derivation");
|
||||
os_free(rnd);
|
||||
os_free(data->key_data);
|
||||
data->key_data = NULL;
|
||||
return -1;
|
||||
}
|
||||
os_memcpy(rnd, keys.client_random, keys.client_random_len);
|
||||
os_memcpy(rnd + keys.client_random_len, keys.server_random,
|
||||
keys.server_random_len);
|
||||
|
||||
if (tls_prf(keys.inner_secret, keys.inner_secret_len,
|
||||
"ttls v1 keying material", rnd, keys.client_random_len +
|
||||
keys.server_random_len, data->key_data, EAP_TLS_KEY_LEN)) {
|
||||
wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive key");
|
||||
os_free(rnd);
|
||||
os_free(data->key_data);
|
||||
data->key_data = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
wpa_hexdump(MSG_DEBUG, "EAP-TTLS: client/server random",
|
||||
rnd, keys.client_random_len + keys.server_random_len);
|
||||
wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: TLS/IA inner secret",
|
||||
keys.inner_secret, keys.inner_secret_len);
|
||||
|
||||
os_free(rnd);
|
||||
|
||||
wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived key",
|
||||
data->key_data, EAP_TLS_KEY_LEN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* EAP_TTLS_VERSION */
|
||||
|
||||
|
||||
static u8 * eap_ttls_implicit_challenge(struct eap_sm *sm,
|
||||
struct eap_ttls_data *data, size_t len)
|
||||
{
|
||||
#if EAP_TTLS_VERSION > 0
|
||||
struct tls_keys keys;
|
||||
u8 *challenge, *rnd;
|
||||
#endif /* EAP_TTLS_VERSION */
|
||||
|
||||
if (data->ttls_version == 0) {
|
||||
return eap_peer_tls_derive_key(sm, &data->ssl,
|
||||
"ttls challenge", len);
|
||||
}
|
||||
|
||||
#if EAP_TTLS_VERSION > 0
|
||||
|
||||
os_memset(&keys, 0, sizeof(keys));
|
||||
if (tls_connection_get_keys(sm->ssl_ctx, data->ssl.conn, &keys) ||
|
||||
keys.client_random == NULL || keys.server_random == NULL ||
|
||||
keys.inner_secret == NULL) {
|
||||
wpa_printf(MSG_INFO, "EAP-TTLS: Could not get inner secret, "
|
||||
"client random, or server random to derive "
|
||||
"implicit challenge");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rnd = os_malloc(keys.client_random_len + keys.server_random_len);
|
||||
challenge = os_malloc(len);
|
||||
if (rnd == NULL || challenge == NULL) {
|
||||
wpa_printf(MSG_INFO, "EAP-TTLS: No memory for implicit "
|
||||
"challenge derivation");
|
||||
os_free(rnd);
|
||||
os_free(challenge);
|
||||
return NULL;
|
||||
}
|
||||
os_memcpy(rnd, keys.server_random, keys.server_random_len);
|
||||
os_memcpy(rnd + keys.server_random_len, keys.client_random,
|
||||
keys.client_random_len);
|
||||
|
||||
if (tls_prf(keys.inner_secret, keys.inner_secret_len,
|
||||
"inner application challenge", rnd,
|
||||
keys.client_random_len + keys.server_random_len,
|
||||
challenge, len)) {
|
||||
wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive implicit "
|
||||
"challenge");
|
||||
os_free(rnd);
|
||||
os_free(challenge);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
os_free(rnd);
|
||||
|
||||
wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived implicit challenge",
|
||||
challenge, len);
|
||||
|
||||
return challenge;
|
||||
|
||||
#else /* EAP_TTLS_VERSION */
|
||||
|
||||
return NULL;
|
||||
|
||||
#endif /* EAP_TTLS_VERSION */
|
||||
}
|
||||
|
||||
|
||||
static void eap_ttlsv1_phase2_eap_finish(struct eap_sm *sm,
|
||||
struct eap_ttls_data *data,
|
||||
struct eap_method_ret *ret)
|
||||
{
|
||||
#if EAP_TTLS_VERSION > 0
|
||||
if (data->ttls_version > 0) {
|
||||
const struct eap_method *m = data->phase2_method;
|
||||
void *priv = data->phase2_priv;
|
||||
|
||||
/* TTLSv1 requires TLS/IA FinalPhaseFinished */
|
||||
if (ret->decision == DECISION_UNCOND_SUCC)
|
||||
ret->decision = DECISION_COND_SUCC;
|
||||
ret->methodState = METHOD_CONT;
|
||||
|
||||
if (ret->decision == DECISION_COND_SUCC &&
|
||||
m->isKeyAvailable && m->getKey &&
|
||||
m->isKeyAvailable(sm, priv)) {
|
||||
u8 *key;
|
||||
size_t key_len;
|
||||
key = m->getKey(sm, priv, &key_len);
|
||||
if (key) {
|
||||
eap_ttls_ia_permute_inner_secret(
|
||||
sm, data, key, key_len);
|
||||
os_free(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* EAP_TTLS_VERSION */
|
||||
return eap_peer_tls_derive_key(sm, &data->ssl, "ttls challenge", len);
|
||||
}
|
||||
|
||||
|
||||
@ -494,7 +282,6 @@ static int eap_ttls_phase2_eap_process(struct eap_sm *sm,
|
||||
ret->methodState = iret.methodState;
|
||||
ret->decision = iret.decision;
|
||||
}
|
||||
eap_ttlsv1_phase2_eap_finish(sm, data, ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -615,26 +402,6 @@ static int eap_ttls_phase2_request_eap(struct eap_sm *sm,
|
||||
}
|
||||
|
||||
|
||||
static void eap_ttlsv1_permute_inner(struct eap_sm *sm,
|
||||
struct eap_ttls_data *data)
|
||||
{
|
||||
#if EAP_TTLS_VERSION > 0
|
||||
u8 session_key[2 * MSCHAPV2_KEY_LEN];
|
||||
|
||||
if (data->ttls_version == 0)
|
||||
return;
|
||||
|
||||
get_asymetric_start_key(data->master_key, session_key,
|
||||
MSCHAPV2_KEY_LEN, 0, 0);
|
||||
get_asymetric_start_key(data->master_key,
|
||||
session_key + MSCHAPV2_KEY_LEN,
|
||||
MSCHAPV2_KEY_LEN, 1, 0);
|
||||
eap_ttls_ia_permute_inner_secret(sm, data, session_key,
|
||||
sizeof(session_key));
|
||||
#endif /* EAP_TTLS_VERSION */
|
||||
}
|
||||
|
||||
|
||||
static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm,
|
||||
struct eap_ttls_data *data,
|
||||
struct eap_method_ret *ret,
|
||||
@ -702,8 +469,6 @@ static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm,
|
||||
}
|
||||
data->auth_response_valid = 1;
|
||||
|
||||
eap_ttlsv1_permute_inner(sm, data);
|
||||
|
||||
pos += 24;
|
||||
os_free(challenge);
|
||||
AVP_PAD(buf, pos);
|
||||
@ -711,7 +476,7 @@ static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm,
|
||||
wpabuf_put(msg, pos - buf);
|
||||
*resp = msg;
|
||||
|
||||
if (sm->workaround && data->ttls_version == 0) {
|
||||
if (sm->workaround) {
|
||||
/* At least FreeRADIUS seems to be terminating
|
||||
* EAP-TTLS/MSHCAPV2 without the expected MS-CHAP-v2 Success
|
||||
* packet. */
|
||||
@ -798,17 +563,10 @@ static int eap_ttls_phase2_request_mschap(struct eap_sm *sm,
|
||||
wpabuf_put(msg, pos - buf);
|
||||
*resp = msg;
|
||||
|
||||
if (data->ttls_version > 0) {
|
||||
/* EAP-TTLSv1 uses TLS/IA FinalPhaseFinished to report success,
|
||||
* so do not allow connection to be terminated yet. */
|
||||
ret->methodState = METHOD_CONT;
|
||||
ret->decision = DECISION_COND_SUCC;
|
||||
} else {
|
||||
/* EAP-TTLS/MSCHAP does not provide tunneled success
|
||||
* notification, so assume that Phase2 succeeds. */
|
||||
ret->methodState = METHOD_DONE;
|
||||
ret->decision = DECISION_COND_SUCC;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -859,17 +617,10 @@ static int eap_ttls_phase2_request_pap(struct eap_sm *sm,
|
||||
wpabuf_put(msg, pos - buf);
|
||||
*resp = msg;
|
||||
|
||||
if (data->ttls_version > 0) {
|
||||
/* EAP-TTLSv1 uses TLS/IA FinalPhaseFinished to report success,
|
||||
* so do not allow connection to be terminated yet. */
|
||||
ret->methodState = METHOD_CONT;
|
||||
ret->decision = DECISION_COND_SUCC;
|
||||
} else {
|
||||
/* EAP-TTLS/PAP does not provide tunneled success notification,
|
||||
* so assume that Phase2 succeeds. */
|
||||
ret->methodState = METHOD_DONE;
|
||||
ret->decision = DECISION_COND_SUCC;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -942,17 +693,10 @@ static int eap_ttls_phase2_request_chap(struct eap_sm *sm,
|
||||
wpabuf_put(msg, pos - buf);
|
||||
*resp = msg;
|
||||
|
||||
if (data->ttls_version > 0) {
|
||||
/* EAP-TTLSv1 uses TLS/IA FinalPhaseFinished to report success,
|
||||
* so do not allow connection to be terminated yet. */
|
||||
ret->methodState = METHOD_CONT;
|
||||
ret->decision = DECISION_COND_SUCC;
|
||||
} else {
|
||||
/* EAP-TTLS/CHAP does not provide tunneled success
|
||||
* notification, so assume that Phase2 succeeds. */
|
||||
ret->methodState = METHOD_DONE;
|
||||
ret->decision = DECISION_COND_SUCC;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1027,36 +771,6 @@ static int eap_ttls_phase2_request(struct eap_sm *sm,
|
||||
}
|
||||
|
||||
|
||||
#if EAP_TTLS_VERSION > 0
|
||||
static struct wpabuf * eap_ttls_build_phase_finished(
|
||||
struct eap_sm *sm, struct eap_ttls_data *data, int id, int final)
|
||||
{
|
||||
struct wpabuf *req, *buf;
|
||||
|
||||
buf = tls_connection_ia_send_phase_finished(sm->ssl_ctx,
|
||||
data->ssl.conn,
|
||||
final);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
|
||||
req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TTLS,
|
||||
1 + wpabuf_len(buf),
|
||||
EAP_CODE_RESPONSE, id);
|
||||
if (req == NULL) {
|
||||
wpabuf_free(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wpabuf_put_u8(req, data->ttls_version);
|
||||
wpabuf_put_buf(req, buf);
|
||||
wpabuf_free(buf);
|
||||
eap_update_len(req);
|
||||
|
||||
return req;
|
||||
}
|
||||
#endif /* EAP_TTLS_VERSION */
|
||||
|
||||
|
||||
struct ttls_parse_avp {
|
||||
u8 *mschapv2;
|
||||
u8 *eapdata;
|
||||
@ -1366,19 +1080,9 @@ static int eap_ttls_process_phase2_mschapv2(struct eap_sm *sm,
|
||||
|
||||
wpa_printf(MSG_INFO, "EAP-TTLS: Phase 2 MSCHAPV2 "
|
||||
"authentication succeeded");
|
||||
if (data->ttls_version > 0) {
|
||||
/*
|
||||
* EAP-TTLSv1 uses TLS/IA FinalPhaseFinished to report
|
||||
* success, so do not allow connection to be terminated
|
||||
* yet.
|
||||
*/
|
||||
ret->methodState = METHOD_CONT;
|
||||
ret->decision = DECISION_COND_SUCC;
|
||||
} else {
|
||||
ret->methodState = METHOD_DONE;
|
||||
ret->decision = DECISION_UNCOND_SUCC;
|
||||
data->phase2_success = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reply with empty data; authentication server will reply
|
||||
@ -1493,24 +1197,6 @@ static int eap_ttls_process_decrypted(struct eap_sm *sm,
|
||||
}
|
||||
|
||||
|
||||
#if EAP_TTLS_VERSION > 0
|
||||
static void eap_ttls_final_phase_finished(struct eap_sm *sm,
|
||||
struct eap_ttls_data *data,
|
||||
struct eap_method_ret *ret,
|
||||
u8 identifier,
|
||||
struct wpabuf **out_data)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "EAP-TTLS: FinalPhaseFinished received");
|
||||
wpa_printf(MSG_INFO, "EAP-TTLS: TLS/IA authentication succeeded");
|
||||
ret->methodState = METHOD_DONE;
|
||||
ret->decision = DECISION_UNCOND_SUCC;
|
||||
data->phase2_success = 1;
|
||||
*out_data = eap_ttls_build_phase_finished(sm, data, identifier, 1);
|
||||
eap_ttls_v1_derive_key(sm, data);
|
||||
}
|
||||
#endif /* EAP_TTLS_VERSION */
|
||||
|
||||
|
||||
static int eap_ttls_implicit_identity_request(struct eap_sm *sm,
|
||||
struct eap_ttls_data *data,
|
||||
struct eap_method_ret *ret,
|
||||
@ -1627,17 +1313,6 @@ static int eap_ttls_decrypt(struct eap_sm *sm, struct eap_ttls_data *data,
|
||||
if (retval)
|
||||
goto done;
|
||||
|
||||
#if EAP_TTLS_VERSION > 0
|
||||
if (data->ttls_version > 0 &&
|
||||
(in_decrypted == NULL || wpabuf_len(in_decrypted) == 0) &&
|
||||
tls_connection_ia_final_phase_finished(sm->ssl_ctx,
|
||||
data->ssl.conn)) {
|
||||
eap_ttls_final_phase_finished(sm, data, ret, identifier,
|
||||
out_data);
|
||||
goto done;
|
||||
}
|
||||
#endif /* EAP_TTLS_VERSION */
|
||||
|
||||
continue_req:
|
||||
data->phase2_start = 0;
|
||||
|
||||
@ -1662,46 +1337,6 @@ done:
|
||||
}
|
||||
|
||||
|
||||
static int eap_ttls_process_start(struct eap_sm *sm,
|
||||
struct eap_ttls_data *data, u8 flags,
|
||||
struct eap_method_ret *ret)
|
||||
{
|
||||
struct eap_peer_config *config = eap_get_config(sm);
|
||||
|
||||
wpa_printf(MSG_DEBUG, "EAP-TTLS: Start (server ver=%d, own ver=%d)",
|
||||
flags & EAP_TLS_VERSION_MASK, data->ttls_version);
|
||||
#if EAP_TTLS_VERSION > 0
|
||||
if ((flags & EAP_TLS_VERSION_MASK) < data->ttls_version)
|
||||
data->ttls_version = flags & EAP_TLS_VERSION_MASK;
|
||||
if (data->force_ttls_version >= 0 &&
|
||||
data->force_ttls_version != data->ttls_version) {
|
||||
wpa_printf(MSG_WARNING, "EAP-TTLS: Failed to select "
|
||||
"forced TTLS version %d",
|
||||
data->force_ttls_version);
|
||||
ret->methodState = METHOD_DONE;
|
||||
ret->decision = DECISION_FAIL;
|
||||
ret->allowNotifications = FALSE;
|
||||
return -1;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "EAP-TTLS: Using TTLS version %d",
|
||||
data->ttls_version);
|
||||
|
||||
if (data->ttls_version > 0)
|
||||
data->ssl.tls_ia = 1;
|
||||
#endif /* EAP_TTLS_VERSION */
|
||||
if (!data->ssl_initialized &&
|
||||
eap_peer_tls_ssl_init(sm, &data->ssl, config)) {
|
||||
wpa_printf(MSG_INFO, "EAP-TTLS: Failed to initialize SSL.");
|
||||
return -1;
|
||||
}
|
||||
data->ssl_initialized = 1;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "EAP-TTLS: Start");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int eap_ttls_process_handshake(struct eap_sm *sm,
|
||||
struct eap_ttls_data *data,
|
||||
struct eap_method_ret *ret,
|
||||
@ -1725,7 +1360,6 @@ static int eap_ttls_process_handshake(struct eap_sm *sm,
|
||||
ret->methodState = METHOD_MAY_CONT;
|
||||
}
|
||||
data->phase2_start = 1;
|
||||
if (data->ttls_version == 0)
|
||||
eap_ttls_v0_derive_key(sm, data);
|
||||
|
||||
if (*out_data == NULL || wpabuf_len(*out_data) == 0) {
|
||||
@ -1761,7 +1395,7 @@ static void eap_ttls_check_auth_status(struct eap_sm *sm,
|
||||
struct eap_ttls_data *data,
|
||||
struct eap_method_ret *ret)
|
||||
{
|
||||
if (data->ttls_version == 0 && ret->methodState == METHOD_DONE) {
|
||||
if (ret->methodState == METHOD_DONE) {
|
||||
ret->allowNotifications = FALSE;
|
||||
if (ret->decision == DECISION_UNCOND_SUCC ||
|
||||
ret->decision == DECISION_COND_SUCC) {
|
||||
@ -1779,8 +1413,7 @@ static void eap_ttls_check_auth_status(struct eap_sm *sm,
|
||||
}
|
||||
#endif /* EAP_TNC */
|
||||
}
|
||||
} else if (data->ttls_version == 0 &&
|
||||
ret->methodState == METHOD_MAY_CONT &&
|
||||
} else if (ret->methodState == METHOD_MAY_CONT &&
|
||||
(ret->decision == DECISION_UNCOND_SUCC ||
|
||||
ret->decision == DECISION_COND_SUCC)) {
|
||||
wpa_printf(MSG_DEBUG, "EAP-TTLS: Authentication "
|
||||
@ -1808,8 +1441,9 @@ static struct wpabuf * eap_ttls_process(struct eap_sm *sm, void *priv,
|
||||
id = eap_get_id(reqData);
|
||||
|
||||
if (flags & EAP_TLS_FLAGS_START) {
|
||||
if (eap_ttls_process_start(sm, data, flags, ret) < 0)
|
||||
return NULL;
|
||||
wpa_printf(MSG_DEBUG, "EAP-TTLS: Start (server ver=%d, own "
|
||||
"ver=%d)", flags & EAP_TLS_VERSION_MASK,
|
||||
data->ttls_version);
|
||||
|
||||
/* RFC 5281, Ch. 9.2:
|
||||
* "This packet MAY contain additional information in the form
|
||||
@ -1817,13 +1451,6 @@ static struct wpabuf * eap_ttls_process(struct eap_sm *sm, void *priv,
|
||||
* For now, ignore any potential extra data.
|
||||
*/
|
||||
left = 0;
|
||||
} else if (!data->ssl_initialized) {
|
||||
wpa_printf(MSG_DEBUG, "EAP-TTLS: First message did not "
|
||||
"include Start flag");
|
||||
ret->methodState = METHOD_DONE;
|
||||
ret->decision = DECISION_FAIL;
|
||||
ret->allowNotifications = FALSE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
resp = NULL;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* hostapd / EAP-TTLS (RFC 5281)
|
||||
* Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2004-2011, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@ -24,16 +24,7 @@
|
||||
#include "eap_common/eap_ttls.h"
|
||||
|
||||
|
||||
/* Maximum supported TTLS version
|
||||
* 0 = RFC 5281
|
||||
* 1 = draft-funk-eap-ttls-v1-00.txt
|
||||
*/
|
||||
#ifndef EAP_TTLS_VERSION
|
||||
#define EAP_TTLS_VERSION 0 /* TTLSv1 implementation is not yet complete */
|
||||
#endif /* EAP_TTLS_VERSION */
|
||||
|
||||
|
||||
#define MSCHAPV2_KEY_LEN 16
|
||||
#define EAP_TTLS_VERSION 0
|
||||
|
||||
|
||||
static void eap_ttls_reset(struct eap_sm *sm, void *priv);
|
||||
@ -43,17 +34,15 @@ struct eap_ttls_data {
|
||||
struct eap_ssl_data ssl;
|
||||
enum {
|
||||
START, PHASE1, PHASE2_START, PHASE2_METHOD,
|
||||
PHASE2_MSCHAPV2_RESP, PHASE_FINISHED, SUCCESS, FAILURE
|
||||
PHASE2_MSCHAPV2_RESP, SUCCESS, FAILURE
|
||||
} state;
|
||||
|
||||
int ttls_version;
|
||||
int force_version;
|
||||
const struct eap_method *phase2_method;
|
||||
void *phase2_priv;
|
||||
int mschapv2_resp_ok;
|
||||
u8 mschapv2_auth_response[20];
|
||||
u8 mschapv2_ident;
|
||||
int tls_ia_configured;
|
||||
struct wpabuf *pending_phase2_eap_resp;
|
||||
int tnc_started;
|
||||
};
|
||||
@ -72,8 +61,6 @@ static const char * eap_ttls_state_txt(int state)
|
||||
return "PHASE2_METHOD";
|
||||
case PHASE2_MSCHAPV2_RESP:
|
||||
return "PHASE2_MSCHAPV2_RESP";
|
||||
case PHASE_FINISHED:
|
||||
return "PHASE_FINISHED";
|
||||
case SUCCESS:
|
||||
return "SUCCESS";
|
||||
case FAILURE:
|
||||
@ -320,54 +307,8 @@ fail:
|
||||
static u8 * eap_ttls_implicit_challenge(struct eap_sm *sm,
|
||||
struct eap_ttls_data *data, size_t len)
|
||||
{
|
||||
struct tls_keys keys;
|
||||
u8 *challenge, *rnd;
|
||||
|
||||
if (data->ttls_version == 0) {
|
||||
return eap_server_tls_derive_key(sm, &data->ssl,
|
||||
"ttls challenge", len);
|
||||
}
|
||||
|
||||
os_memset(&keys, 0, sizeof(keys));
|
||||
if (tls_connection_get_keys(sm->ssl_ctx, data->ssl.conn, &keys) ||
|
||||
keys.client_random == NULL || keys.server_random == NULL ||
|
||||
keys.inner_secret == NULL) {
|
||||
wpa_printf(MSG_INFO, "EAP-TTLS: Could not get inner secret, "
|
||||
"client random, or server random to derive "
|
||||
"implicit challenge");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rnd = os_malloc(keys.client_random_len + keys.server_random_len);
|
||||
challenge = os_malloc(len);
|
||||
if (rnd == NULL || challenge == NULL) {
|
||||
wpa_printf(MSG_INFO, "EAP-TTLS: No memory for implicit "
|
||||
"challenge derivation");
|
||||
os_free(rnd);
|
||||
os_free(challenge);
|
||||
return NULL;
|
||||
}
|
||||
os_memcpy(rnd, keys.server_random, keys.server_random_len);
|
||||
os_memcpy(rnd + keys.server_random_len, keys.client_random,
|
||||
keys.client_random_len);
|
||||
|
||||
if (tls_prf(keys.inner_secret, keys.inner_secret_len,
|
||||
"inner application challenge", rnd,
|
||||
keys.client_random_len + keys.server_random_len,
|
||||
challenge, len)) {
|
||||
wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive implicit "
|
||||
"challenge");
|
||||
os_free(rnd);
|
||||
os_free(challenge);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
os_free(rnd);
|
||||
|
||||
wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived implicit challenge",
|
||||
challenge, len);
|
||||
|
||||
return challenge;
|
||||
return eap_server_tls_derive_key(sm, &data->ssl, "ttls challenge",
|
||||
len);
|
||||
}
|
||||
|
||||
|
||||
@ -379,27 +320,8 @@ static void * eap_ttls_init(struct eap_sm *sm)
|
||||
if (data == NULL)
|
||||
return NULL;
|
||||
data->ttls_version = EAP_TTLS_VERSION;
|
||||
data->force_version = -1;
|
||||
if (sm->user && sm->user->force_version >= 0) {
|
||||
data->force_version = sm->user->force_version;
|
||||
wpa_printf(MSG_DEBUG, "EAP-TTLS: forcing version %d",
|
||||
data->force_version);
|
||||
data->ttls_version = data->force_version;
|
||||
}
|
||||
data->state = START;
|
||||
|
||||
if (!(tls_capabilities(sm->ssl_ctx) & TLS_CAPABILITY_IA) &&
|
||||
data->ttls_version > 0) {
|
||||
if (data->force_version > 0) {
|
||||
wpa_printf(MSG_INFO, "EAP-TTLS: Forced TTLSv%d and "
|
||||
"TLS library does not support TLS/IA.",
|
||||
data->force_version);
|
||||
eap_ttls_reset(sm, data);
|
||||
return NULL;
|
||||
}
|
||||
data->ttls_version = 0;
|
||||
}
|
||||
|
||||
if (eap_server_tls_ssl_init(sm, &data->ssl, 0)) {
|
||||
wpa_printf(MSG_INFO, "EAP-TTLS: Failed to initialize SSL.");
|
||||
eap_ttls_reset(sm, data);
|
||||
@ -516,14 +438,6 @@ static struct wpabuf * eap_ttls_build_phase2_mschapv2(
|
||||
}
|
||||
|
||||
|
||||
static struct wpabuf * eap_ttls_build_phase_finished(
|
||||
struct eap_sm *sm, struct eap_ttls_data *data, int final)
|
||||
{
|
||||
return tls_connection_ia_send_phase_finished(sm->ssl_ctx,
|
||||
data->ssl.conn, final);
|
||||
}
|
||||
|
||||
|
||||
static struct wpabuf * eap_ttls_buildReq(struct eap_sm *sm, void *priv, u8 id)
|
||||
{
|
||||
struct eap_ttls_data *data = priv;
|
||||
@ -559,11 +473,6 @@ static struct wpabuf * eap_ttls_buildReq(struct eap_sm *sm, void *priv, u8 id)
|
||||
data->ssl.tls_out_pos = 0;
|
||||
data->ssl.tls_out = eap_ttls_build_phase2_mschapv2(sm, data);
|
||||
break;
|
||||
case PHASE_FINISHED:
|
||||
wpabuf_free(data->ssl.tls_out);
|
||||
data->ssl.tls_out_pos = 0;
|
||||
data->ssl.tls_out = eap_ttls_build_phase_finished(sm, data, 1);
|
||||
break;
|
||||
default:
|
||||
wpa_printf(MSG_DEBUG, "EAP-TTLS: %s - unexpected state %d",
|
||||
__func__, data->state);
|
||||
@ -591,37 +500,6 @@ static Boolean eap_ttls_check(struct eap_sm *sm, void *priv,
|
||||
}
|
||||
|
||||
|
||||
static int eap_ttls_ia_permute_inner_secret(struct eap_sm *sm,
|
||||
struct eap_ttls_data *data,
|
||||
const u8 *key, size_t key_len)
|
||||
{
|
||||
u8 *buf;
|
||||
size_t buf_len;
|
||||
int ret;
|
||||
|
||||
if (key) {
|
||||
buf_len = 2 + key_len;
|
||||
buf = os_malloc(buf_len);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
WPA_PUT_BE16(buf, key_len);
|
||||
os_memcpy(buf + 2, key, key_len);
|
||||
} else {
|
||||
buf = NULL;
|
||||
buf_len = 0;
|
||||
}
|
||||
|
||||
wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Session keys for TLS/IA inner "
|
||||
"secret permutation", buf, buf_len);
|
||||
ret = tls_connection_ia_permute_inner_secret(sm->ssl_ctx,
|
||||
data->ssl.conn,
|
||||
buf, buf_len);
|
||||
os_free(buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void eap_ttls_process_phase2_pap(struct eap_sm *sm,
|
||||
struct eap_ttls_data *data,
|
||||
const u8 *user_password,
|
||||
@ -644,8 +522,7 @@ static void eap_ttls_process_phase2_pap(struct eap_sm *sm,
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "EAP-TTLS/PAP: Correct user password");
|
||||
eap_ttls_state(data, data->ttls_version > 0 ? PHASE_FINISHED :
|
||||
SUCCESS);
|
||||
eap_ttls_state(data, SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
@ -701,8 +578,7 @@ static void eap_ttls_process_phase2_chap(struct eap_sm *sm,
|
||||
|
||||
if (os_memcmp(hash, password + 1, EAP_TTLS_CHAP_PASSWORD_LEN) == 0) {
|
||||
wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Correct user password");
|
||||
eap_ttls_state(data, data->ttls_version > 0 ? PHASE_FINISHED :
|
||||
SUCCESS);
|
||||
eap_ttls_state(data, SUCCESS);
|
||||
} else {
|
||||
wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Invalid user password");
|
||||
eap_ttls_state(data, FAILURE);
|
||||
@ -762,8 +638,7 @@ static void eap_ttls_process_phase2_mschap(struct eap_sm *sm,
|
||||
|
||||
if (os_memcmp(nt_response, response + 2 + 24, 24) == 0) {
|
||||
wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Correct response");
|
||||
eap_ttls_state(data, data->ttls_version > 0 ? PHASE_FINISHED :
|
||||
SUCCESS);
|
||||
eap_ttls_state(data, SUCCESS);
|
||||
} else {
|
||||
wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Invalid NT-Response");
|
||||
wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAP: Received",
|
||||
@ -863,30 +738,6 @@ static void eap_ttls_process_phase2_mschapv2(struct eap_sm *sm,
|
||||
wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Correct "
|
||||
"NT-Response");
|
||||
data->mschapv2_resp_ok = 1;
|
||||
if (data->ttls_version > 0) {
|
||||
const u8 *pw_hash;
|
||||
u8 pw_hash_buf[16], pw_hash_hash[16], master_key[16];
|
||||
u8 session_key[2 * MSCHAPV2_KEY_LEN];
|
||||
|
||||
if (sm->user->password_hash)
|
||||
pw_hash = sm->user->password;
|
||||
else {
|
||||
nt_password_hash(sm->user->password,
|
||||
sm->user->password_len,
|
||||
pw_hash_buf);
|
||||
pw_hash = pw_hash_buf;
|
||||
}
|
||||
hash_nt_password_hash(pw_hash, pw_hash_hash);
|
||||
get_master_key(pw_hash_hash, nt_response, master_key);
|
||||
get_asymetric_start_key(master_key, session_key,
|
||||
MSCHAPV2_KEY_LEN, 0, 0);
|
||||
get_asymetric_start_key(master_key,
|
||||
session_key + MSCHAPV2_KEY_LEN,
|
||||
MSCHAPV2_KEY_LEN, 1, 0);
|
||||
eap_ttls_ia_permute_inner_secret(sm, data,
|
||||
session_key,
|
||||
sizeof(session_key));
|
||||
}
|
||||
|
||||
if (sm->user->password_hash) {
|
||||
generate_authenticator_response_pwhash(
|
||||
@ -1030,16 +881,6 @@ static void eap_ttls_process_phase2_eap_response(struct eap_sm *sm,
|
||||
}
|
||||
break;
|
||||
case PHASE2_METHOD:
|
||||
if (data->ttls_version > 0) {
|
||||
if (m->getKey) {
|
||||
u8 *key;
|
||||
size_t key_len;
|
||||
key = m->getKey(sm, priv, &key_len);
|
||||
eap_ttls_ia_permute_inner_secret(sm, data,
|
||||
key, key_len);
|
||||
}
|
||||
eap_ttls_state(data, PHASE_FINISHED);
|
||||
} else
|
||||
eap_ttls_state(data, SUCCESS);
|
||||
break;
|
||||
case FAILURE:
|
||||
@ -1130,23 +971,6 @@ static void eap_ttls_process_phase2(struct eap_sm *sm,
|
||||
return;
|
||||
}
|
||||
|
||||
if (data->state == PHASE_FINISHED) {
|
||||
if (wpabuf_len(in_decrypted) == 0 &&
|
||||
tls_connection_ia_final_phase_finished(sm->ssl_ctx,
|
||||
data->ssl.conn)) {
|
||||
wpa_printf(MSG_DEBUG, "EAP-TTLS: FinalPhaseFinished "
|
||||
"received");
|
||||
eap_ttls_state(data, SUCCESS);
|
||||
} else {
|
||||
wpa_printf(MSG_INFO, "EAP-TTLS: Did not receive valid "
|
||||
"FinalPhaseFinished");
|
||||
eap_ttls_state(data, FAILURE);
|
||||
}
|
||||
|
||||
wpabuf_free(in_decrypted);
|
||||
return;
|
||||
}
|
||||
|
||||
wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TTLS: Decrypted Phase 2 EAP",
|
||||
in_decrypted);
|
||||
|
||||
@ -1245,15 +1069,6 @@ static int eap_ttls_process_version(struct eap_sm *sm, void *priv,
|
||||
data->ttls_version = peer_version;
|
||||
}
|
||||
|
||||
if (data->ttls_version > 0 && !data->tls_ia_configured) {
|
||||
if (tls_connection_set_ia(sm->ssl_ctx, data->ssl.conn, 1)) {
|
||||
wpa_printf(MSG_INFO, "EAP-TTLS: Failed to enable "
|
||||
"TLS/IA");
|
||||
return -1;
|
||||
}
|
||||
data->tls_ia_configured = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1270,7 +1085,6 @@ static void eap_ttls_process_msg(struct eap_sm *sm, void *priv,
|
||||
break;
|
||||
case PHASE2_START:
|
||||
case PHASE2_METHOD:
|
||||
case PHASE_FINISHED:
|
||||
eap_ttls_process_phase2(sm, data, data->ssl.tls_in);
|
||||
eap_ttls_start_tnc(sm, data);
|
||||
break;
|
||||
@ -1279,8 +1093,7 @@ static void eap_ttls_process_msg(struct eap_sm *sm, void *priv,
|
||||
0) {
|
||||
wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Peer "
|
||||
"acknowledged response");
|
||||
eap_ttls_state(data, data->ttls_version > 0 ?
|
||||
PHASE_FINISHED : SUCCESS);
|
||||
eap_ttls_state(data, SUCCESS);
|
||||
} else if (!data->mschapv2_resp_ok) {
|
||||
wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Peer "
|
||||
"acknowledged error");
|
||||
@ -1321,54 +1134,6 @@ static Boolean eap_ttls_isDone(struct eap_sm *sm, void *priv)
|
||||
}
|
||||
|
||||
|
||||
static u8 * eap_ttls_v1_derive_key(struct eap_sm *sm,
|
||||
struct eap_ttls_data *data)
|
||||
{
|
||||
struct tls_keys keys;
|
||||
u8 *rnd, *key;
|
||||
|
||||
os_memset(&keys, 0, sizeof(keys));
|
||||
if (tls_connection_get_keys(sm->ssl_ctx, data->ssl.conn, &keys) ||
|
||||
keys.client_random == NULL || keys.server_random == NULL ||
|
||||
keys.inner_secret == NULL) {
|
||||
wpa_printf(MSG_INFO, "EAP-TTLS: Could not get inner secret, "
|
||||
"client random, or server random to derive keying "
|
||||
"material");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rnd = os_malloc(keys.client_random_len + keys.server_random_len);
|
||||
key = os_malloc(EAP_TLS_KEY_LEN);
|
||||
if (rnd == NULL || key == NULL) {
|
||||
wpa_printf(MSG_INFO, "EAP-TTLS: No memory for key derivation");
|
||||
os_free(rnd);
|
||||
os_free(key);
|
||||
return NULL;
|
||||
}
|
||||
os_memcpy(rnd, keys.client_random, keys.client_random_len);
|
||||
os_memcpy(rnd + keys.client_random_len, keys.server_random,
|
||||
keys.server_random_len);
|
||||
|
||||
if (tls_prf(keys.inner_secret, keys.inner_secret_len,
|
||||
"ttls v1 keying material", rnd, keys.client_random_len +
|
||||
keys.server_random_len, key, EAP_TLS_KEY_LEN)) {
|
||||
wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive key");
|
||||
os_free(rnd);
|
||||
os_free(key);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wpa_hexdump(MSG_DEBUG, "EAP-TTLS: client/server random",
|
||||
rnd, keys.client_random_len + keys.server_random_len);
|
||||
wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: TLS/IA inner secret",
|
||||
keys.inner_secret, keys.inner_secret_len);
|
||||
|
||||
os_free(rnd);
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
|
||||
static u8 * eap_ttls_getKey(struct eap_sm *sm, void *priv, size_t *len)
|
||||
{
|
||||
struct eap_ttls_data *data = priv;
|
||||
@ -1377,14 +1142,9 @@ static u8 * eap_ttls_getKey(struct eap_sm *sm, void *priv, size_t *len)
|
||||
if (data->state != SUCCESS)
|
||||
return NULL;
|
||||
|
||||
if (data->ttls_version == 0) {
|
||||
eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
|
||||
"ttls keying material",
|
||||
EAP_TLS_KEY_LEN);
|
||||
} else {
|
||||
eapKeyData = eap_ttls_v1_derive_key(sm, data);
|
||||
}
|
||||
|
||||
if (eapKeyData) {
|
||||
*len = EAP_TLS_KEY_LEN;
|
||||
wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived key",
|
||||
|
@ -829,10 +829,6 @@ ifeq ($(CONFIG_TLS), gnutls)
|
||||
ifdef TLS_FUNCS
|
||||
OBJS += ../src/crypto/tls_gnutls.o
|
||||
LIBS += -lgnutls -lgpg-error
|
||||
ifdef CONFIG_GNUTLS_EXTRA
|
||||
CFLAGS += -DCONFIG_GNUTLS_EXTRA
|
||||
LIBS += -lgnutls-extra
|
||||
endif
|
||||
endif
|
||||
OBJS += ../src/crypto/crypto_gnutls.o
|
||||
OBJS_p += ../src/crypto/crypto_gnutls.o
|
||||
|
@ -322,19 +322,11 @@ CONFIG_PEERKEY=y
|
||||
|
||||
# Select TLS implementation
|
||||
# openssl = OpenSSL (default)
|
||||
# gnutls = GnuTLS (needed for TLS/IA, see also CONFIG_GNUTLS_EXTRA)
|
||||
# gnutls = GnuTLS
|
||||
# internal = Internal TLSv1 implementation (experimental)
|
||||
# none = Empty template
|
||||
#CONFIG_TLS=openssl
|
||||
|
||||
# Whether to enable TLS/IA support, which is required for EAP-TTLSv1.
|
||||
# You need CONFIG_TLS=gnutls for this to have any effect. Please note that
|
||||
# even though the core GnuTLS library is released under LGPL, this extra
|
||||
# library uses GPL and as such, the terms of GPL apply to the combination
|
||||
# of wpa_supplicant and GnuTLS if this option is enabled. BSD license may not
|
||||
# apply for distribution of the resulting binary.
|
||||
#CONFIG_GNUTLS_EXTRA=y
|
||||
|
||||
# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.1)
|
||||
# can be enabled to get a stronger construction of messages when block ciphers
|
||||
# are used. It should be noted that some existing TLS v1.0 -based
|
||||
|
Loading…
Reference in New Issue
Block a user