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:
Jouni Malinen 2011-09-25 21:28:32 +03:00
parent e655e1f512
commit fd2f2d0489
15 changed files with 48 additions and 1171 deletions

View file

@ -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

View file

@ -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.

View file

@ -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);

View file

@ -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 */
}

View file

@ -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,

View file

@ -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;
}

View file

@ -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,

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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()
*/

View file

@ -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);
eap_ttls_deinit(sm, data);
return NULL;
}
data->ttls_version = 0;
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;
}
#endif /* EAP_TTLS_VERSION */
return data;
}
@ -176,8 +144,7 @@ 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);
eap_peer_tls_ssl_deinit(sm, &data->ssl);
os_free(data->key_data);
wpabuf_free(data->pending_phase2_req);
os_free(data);
@ -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;
}
/* 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;
}
/* 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;
}
/* 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;
}
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,8 +1360,7 @@ 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);
eap_ttls_v0_derive_key(sm, data);
if (*out_data == NULL || wpabuf_len(*out_data) == 0) {
if (eap_ttls_decrypt(sm, data, ret, identifier,
@ -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;

View file

@ -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,17 +881,7 @@ 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);
eap_ttls_state(data, SUCCESS);
break;
case FAILURE:
break;
@ -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);
}
eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
"ttls keying material",
EAP_TLS_KEY_LEN);
if (eapKeyData) {
*len = EAP_TLS_KEY_LEN;
wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived key",

View file

@ -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

View file

@ -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