aboutsummaryrefslogtreecommitdiffstats
path: root/src/charon
diff options
context:
space:
mode:
authorMartin Willi <martin@revosec.ch>2010-02-01 10:25:44 +0000
committerMartin Willi <martin@revosec.ch>2010-08-03 15:39:24 +0200
commit4ef946dd64876df4ffabf49d4d7cbf42c6958008 (patch)
tree12d65bc1913dd808ea5ab8d77ff3a8a99b0b292b /src/charon
parent3e962b0843c17e220592718f498c513aa52796fd (diff)
downloadstrongswan-4ef946dd64876df4ffabf49d4d7cbf42c6958008.tar.bz2
strongswan-4ef946dd64876df4ffabf49d4d7cbf42c6958008.tar.xz
Implemented a tls_reader class to simplify TLS data parsing
Diffstat (limited to 'src/charon')
-rw-r--r--src/charon/plugins/eap_tls/Makefile.am1
-rw-r--r--src/charon/plugins/eap_tls/tls/tls_fragmentation.c60
-rw-r--r--src/charon/plugins/eap_tls/tls/tls_handshake.h5
-rw-r--r--src/charon/plugins/eap_tls/tls/tls_peer.c154
-rw-r--r--src/charon/plugins/eap_tls/tls/tls_reader.c193
-rw-r--r--src/charon/plugins/eap_tls/tls/tls_reader.h124
-rw-r--r--src/charon/plugins/eap_tls/tls/tls_server.c2
7 files changed, 419 insertions, 120 deletions
diff --git a/src/charon/plugins/eap_tls/Makefile.am b/src/charon/plugins/eap_tls/Makefile.am
index ff42d024d..f5870faaf 100644
--- a/src/charon/plugins/eap_tls/Makefile.am
+++ b/src/charon/plugins/eap_tls/Makefile.am
@@ -11,6 +11,7 @@ libstrongswan_eap_tls_la_SOURCES = eap_tls_plugin.h eap_tls_plugin.c \
tls/tls_compression.h tls/tls_compression.c \
tls/tls_fragmentation.h tls/tls_fragmentation.c \
tls/tls_crypto.h tls/tls_crypto.c \
+ tls/tls_reader.h tls/tls_reader.c \
tls/tls_peer.h tls/tls_peer.c \
tls/tls_server.h tls/tls_server.c \
tls/tls_handshake.h
diff --git a/src/charon/plugins/eap_tls/tls/tls_fragmentation.c b/src/charon/plugins/eap_tls/tls/tls_fragmentation.c
index 0d38e4890..e23b96fea 100644
--- a/src/charon/plugins/eap_tls/tls/tls_fragmentation.c
+++ b/src/charon/plugins/eap_tls/tls/tls_fragmentation.c
@@ -15,6 +15,8 @@
#include "tls_fragmentation.h"
+#include "tls_reader.h"
+
#include <daemon.h>
typedef struct private_tls_fragmentation_t private_tls_fragmentation_t;
@@ -73,15 +75,17 @@ typedef union {
* Process TLS handshake protocol data
*/
static status_t process_handshake(private_tls_fragmentation_t *this,
- chunk_t data)
+ tls_reader_t *reader)
{
- while (data.len)
+ while (reader->remaining(reader))
{
+ tls_reader_t *msg;
+ u_int8_t type;
u_int32_t len;
status_t status;
- tls_handshake_header_t *hdr;
+ chunk_t data;
- if (data.len == 0 || data.len > MAX_TLS_FRAGMENT_LEN)
+ if (reader->remaining(reader) > MAX_TLS_FRAGMENT_LEN)
{
DBG1(DBG_IKE, "TLS fragment has invalid length");
return FAILED;
@@ -89,33 +93,38 @@ static status_t process_handshake(private_tls_fragmentation_t *this,
if (this->input.len == 0)
{ /* new handshake message */
- if (data.len < sizeof(tls_handshake_header_t))
+ if (!reader->read_uint8(reader, &type) ||
+ !reader->read_uint24(reader, &len))
{
- DBG1(DBG_IKE, "initial TLS fragment too short %B", &data);
return FAILED;
}
- hdr = (tls_handshake_header_t*)data.ptr;
- len = untoh32(&hdr->length) & 0x00FFFFFF;
- this->type = hdr->type;
+ this->type = type;
if (len > MAX_TLS_HANDSHAKE_LEN)
{
DBG1(DBG_IKE, "TLS handshake message exceeds maximum length");
return FAILED;
}
- this->input = len ? chunk_alloc(len) : chunk_empty;
+ chunk_free(&this->input);
this->inpos = 0;
- data = chunk_skip(data, sizeof(tls_handshake_header_t));
+ if (len)
+ {
+ this->input = chunk_alloc(len);
+ }
}
- len = min(this->input.len - this->inpos, data.len);
+ len = min(this->input.len - this->inpos, reader->remaining(reader));
+ if (!reader->read_data(reader, len, &data))
+ {
+ return FAILED;
+ }
memcpy(this->input.ptr + this->inpos, data.ptr, len);
this->inpos += len;
- data = chunk_skip(data, len);
if (this->input.len == this->inpos)
{ /* message completely defragmented, process */
- status = this->handshake->process(this->handshake,
- this->type, this->input);
+ msg = tls_reader_create(this->input);
+ status = this->handshake->process(this->handshake, this->type, msg);
+ msg->destroy(msg);
chunk_free(&this->input);
if (status != NEED_MORE)
{
@@ -129,23 +138,34 @@ static status_t process_handshake(private_tls_fragmentation_t *this,
METHOD(tls_fragmentation_t, process, status_t,
private_tls_fragmentation_t *this, tls_content_type_t type, chunk_t data)
{
+ tls_reader_t *reader;
+ status_t status;
+
+ reader = tls_reader_create(data);
switch (type)
{
case TLS_CHANGE_CIPHER_SPEC:
/* TODO: handle ChangeCipherSpec */
- return FAILED;
+ status = FAILED;
+ break;
case TLS_ALERT:
/* TODO: handle Alert */
- return FAILED;
+ status = FAILED;
+ break;
case TLS_HANDSHAKE:
- return process_handshake(this, data);
+ status = process_handshake(this, reader);
+ break;
case TLS_APPLICATION_DATA:
/* skip application data */
- return NEED_MORE;
+ status = NEED_MORE;
+ break;
default:
DBG1(DBG_IKE, "received unknown TLS content type %d, ignored", type);
- return NEED_MORE;
+ status = NEED_MORE;
+ break;
}
+ reader->destroy(reader);
+ return status;
}
METHOD(tls_fragmentation_t, build, status_t,
diff --git a/src/charon/plugins/eap_tls/tls/tls_handshake.h b/src/charon/plugins/eap_tls/tls/tls_handshake.h
index 28174cf8a..cfdeae5d7 100644
--- a/src/charon/plugins/eap_tls/tls/tls_handshake.h
+++ b/src/charon/plugins/eap_tls/tls/tls_handshake.h
@@ -24,6 +24,7 @@
typedef struct tls_handshake_t tls_handshake_t;
#include "tls.h"
+#include "tls_reader.h"
/**
* TLS handshake state machine interface.
@@ -34,14 +35,14 @@ struct tls_handshake_t {
* Process received TLS handshake message.
*
* @param type TLS handshake message type
- * @param data TLS handshake data
+ * @param reader TLS data buffer
* @return
* - SUCCESS if handshake complete
* - FAILED if handshake failed
* - NEED_MORE if another invocation of process/build needed
*/
status_t (*process)(tls_handshake_t *this,
- tls_handshake_type_t type, chunk_t data);
+ tls_handshake_type_t type, tls_reader_t *reader);
/**
* Build TLS handshake messages to send out.
diff --git a/src/charon/plugins/eap_tls/tls/tls_peer.c b/src/charon/plugins/eap_tls/tls/tls_peer.c
index bb108fe9b..bd84ff81c 100644
--- a/src/charon/plugins/eap_tls/tls/tls_peer.c
+++ b/src/charon/plugins/eap_tls/tls/tls_peer.c
@@ -56,148 +56,108 @@ struct private_tls_peer_t {
/**
* Process a server hello message
*/
-static status_t process_server_hello(private_tls_peer_t *this, chunk_t data)
+static status_t process_server_hello(private_tls_peer_t *this,
+ tls_reader_t *reader)
{
- if (data.len >= 38)
+ u_int8_t compression;
+ u_int16_t version, cipher;
+ u_int32_t gmt;
+ chunk_t random, session, ext = chunk_empty;
+
+ if (!reader->read_uint16(reader, &version) ||
+ !reader->read_uint32(reader, &gmt) ||
+ !reader->read_data(reader, 28, &random) ||
+ !reader->read_data8(reader, &session) ||
+ !reader->read_uint16(reader, &cipher) ||
+ !reader->read_uint8(reader, &compression) ||
+ (reader->remaining(reader) && !reader->read_data16(reader, &ext)))
{
- tls_version_t version;
-
- struct __attribute__((packed)) {
- u_int16_t version;
- struct __attribute__((packed)) {
- u_int32_t gmt;
- u_int8_t bytes[28];
- } random;
- struct __attribute__((packed)) {
- u_int8_t len;
- /* points to len */
- u_int8_t id[data.ptr[34]];
- } session;
- u_int16_t cipher;
- u_int8_t compression;
- char extensions[];
- } *hello = (void*)data.ptr;
-
- if (sizeof(*hello) > data.len)
- {
- DBG1(DBG_IKE, "received invalid ServerHello");
- return FAILED;
- }
-
- version = untoh16(&hello->version);
- if (version < this->tls->get_version(this->tls))
- {
- this->tls->set_version(this->tls, version);
- }
- return NEED_MORE;
+ DBG1(DBG_IKE, "received invalid ServerHello");
+ return FAILED;
}
- DBG1(DBG_IKE, "server hello has %d bytes", data.len);
- return FAILED;
+ if (version < this->tls->get_version(this->tls))
+ {
+ this->tls->set_version(this->tls, version);
+ }
+ return NEED_MORE;
}
/**
* Process a Certificate message
*/
-static status_t process_certificate(private_tls_peer_t *this, chunk_t data)
+static status_t process_certificate(private_tls_peer_t *this,
+ tls_reader_t *reader)
{
- if (data.len > 3)
- {
- u_int32_t total;
+ certificate_t *cert;
+ tls_reader_t *certs;
+ chunk_t data;
- total = untoh32(data.ptr) >> 8;
- data = chunk_skip(data, 3);
- if (total != data.len)
+ if (!reader->read_data24(reader, &data))
+ {
+ return FAILED;
+ }
+ certs = tls_reader_create(data);
+ while (certs->remaining(certs))
+ {
+ if (!certs->read_data24(certs, &data))
{
- DBG1(DBG_IKE, "certificate chain length invalid");
+ certs->destroy(certs);
return FAILED;
}
- while (data.len > 3)
+ cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
+ BUILD_BLOB_ASN1_DER, data, BUILD_END);
+ if (cert)
{
- certificate_t *cert;
- u_int32_t len;
-
- len = untoh32(data.ptr) >> 8;
- data = chunk_skip(data, 3);
- if (len > data.len)
- {
- DBG1(DBG_IKE, "certificate length invalid");
- return FAILED;
- }
- cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
- BUILD_BLOB_ASN1_DER, chunk_create(data.ptr, len), BUILD_END);
- if (cert)
- {
- DBG1(DBG_IKE, "got certificate: %Y", cert->get_subject(cert));
- cert->destroy(cert);
- }
- data = chunk_skip(data, len);
+ DBG1(DBG_IKE, "got certificate: %Y", cert->get_subject(cert));
+ cert->destroy(cert);
}
}
+ certs->destroy(certs);
return NEED_MORE;
}
/**
* Process a Certificate message
*/
-static status_t process_certreq(private_tls_peer_t *this, chunk_t data)
+static status_t process_certreq(private_tls_peer_t *this, tls_reader_t *reader)
{
- struct __attribute__((packed)) {
- u_int8_t len;
- u_int8_t types[];
- } *certificate;
- struct __attribute__((packed)) {
- u_int16_t len;
- struct __attribute__((packed)) {
- u_int8_t hash;
- u_int8_t sig;
- } types[];
- } *alg;
- u_int16_t len;
+ chunk_t types, hashsig, data;
+ tls_reader_t *authorities;
identification_t *id;
- certificate = (void*)data.ptr;
- data = chunk_skip(data, 1);
- if (!data.len || certificate->len > data.len)
+ if (!reader->read_data8(reader, &types))
{
return FAILED;
}
- data = chunk_skip(data, certificate->len);
-
if (this->tls->get_version(this->tls) >= TLS_1_2)
{
- alg = (void*)data.ptr;
- data = chunk_skip(data, 2);
- if (!data.len || untoh16(&alg->len) > data.len)
+ if (!reader->read_data16(reader, &hashsig))
{
return FAILED;
}
- data = chunk_skip(data, untoh16(&alg->len));
}
- if (data.len < 2 || untoh16(data.ptr) != data.len - 2)
+ if (!reader->read_data16(reader, &data))
{
return FAILED;
}
- data = chunk_skip(data, 2);
-
- while (data.len >= 2)
+ authorities = tls_reader_create(data);
+ while (authorities->remaining(authorities))
{
- len = untoh16(data.ptr);
- data = chunk_skip(data, 2);
- if (len > data.len)
+ if (!authorities->read_data16(authorities, &data))
{
+ authorities->destroy(authorities);
return FAILED;
}
- id = identification_create_from_encoding(ID_DER_ASN1_DN,
- chunk_create(data.ptr, len));
+ id = identification_create_from_encoding(ID_DER_ASN1_DN, data);
DBG1(DBG_IKE, "received certificate request for %Y", id);
id->destroy(id);
- data = chunk_skip(data, len);
}
+ authorities->destroy(authorities);
return NEED_MORE;
}
METHOD(tls_handshake_t, process, status_t,
- private_tls_peer_t *this, tls_handshake_type_t type, chunk_t data)
+ private_tls_peer_t *this, tls_handshake_type_t type, tls_reader_t *reader)
{
switch (this->state)
{
@@ -205,11 +165,11 @@ METHOD(tls_handshake_t, process, status_t,
switch (type)
{
case TLS_SERVER_HELLO:
- return process_server_hello(this, data);
+ return process_server_hello(this, reader);
case TLS_CERTIFICATE:
- return process_certificate(this, data);
+ return process_certificate(this, reader);
case TLS_CERTIFICATE_REQUEST:
- return process_certreq(this, data);
+ return process_certreq(this, reader);
case TLS_SERVER_HELLO_DONE:
this->state = STATE_HELLO_DONE;
return NEED_MORE;
diff --git a/src/charon/plugins/eap_tls/tls/tls_reader.c b/src/charon/plugins/eap_tls/tls/tls_reader.c
new file mode 100644
index 000000000..a1911d49b
--- /dev/null
+++ b/src/charon/plugins/eap_tls/tls/tls_reader.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tls_reader.h"
+
+#include <daemon.h>
+
+typedef struct private_tls_reader_t private_tls_reader_t;
+
+/**
+ * Private data of an tls_reader_t object.
+ */
+struct private_tls_reader_t {
+
+ /**
+ * Public tls_reader_t interface.
+ */
+ tls_reader_t public;
+
+ /**
+ * Remaining data to process
+ */
+ chunk_t buf;
+};
+
+METHOD(tls_reader_t, remaining, u_int32_t,
+ private_tls_reader_t *this)
+{
+ return this->buf.len;
+}
+
+METHOD(tls_reader_t, read_uint8, bool,
+ private_tls_reader_t *this, u_int8_t *res)
+{
+ if (this->buf.len < 1)
+ {
+ DBG1(DBG_IKE, "%d bytes insufficient to parse uint%d TLS data",
+ this->buf.len, 8);
+ return FALSE;
+ }
+ *res = this->buf.ptr[0];
+ this->buf = chunk_skip(this->buf, 1);
+ return TRUE;
+}
+
+METHOD(tls_reader_t, read_uint16, bool,
+ private_tls_reader_t *this, u_int16_t *res)
+{
+ if (this->buf.len < 2)
+ {
+ DBG1(DBG_IKE, "%d bytes insufficient to parse uint%d TLS data",
+ this->buf.len, 16);
+ return FALSE;
+ }
+ *res = untoh16(this->buf.ptr);
+ this->buf = chunk_skip(this->buf, 2);
+ return TRUE;
+}
+
+METHOD(tls_reader_t, read_uint24, bool,
+ private_tls_reader_t *this, u_int32_t *res)
+{
+ if (this->buf.len < 3)
+ {
+ DBG1(DBG_IKE, "%d bytes insufficient to parse uint%d TLS data",
+ this->buf.len, 24);
+ return FALSE;
+ }
+ *res = untoh32(this->buf.ptr) >> 8;
+ this->buf = chunk_skip(this->buf, 3);
+ return TRUE;
+}
+
+METHOD(tls_reader_t, read_uint32, bool,
+ private_tls_reader_t *this, u_int32_t *res)
+{
+ if (this->buf.len < 4)
+ {
+ DBG1(DBG_IKE, "%d bytes insufficient to parse uint%d TLS data",
+ this->buf.len, 32);
+ return FALSE;
+ }
+ *res = untoh32(this->buf.ptr);
+ this->buf = chunk_skip(this->buf, 4);
+ return TRUE;
+}
+
+METHOD(tls_reader_t, read_data, bool,
+ private_tls_reader_t *this, u_int32_t len, chunk_t *res)
+{
+ if (this->buf.len < len)
+ {
+ DBG1(DBG_IKE, "%d bytes insufficient to parse %d bytes TLS data",
+ this->buf.len, len);
+ return FALSE;
+ }
+ *res = chunk_create(this->buf.ptr, len);
+ this->buf = chunk_skip(this->buf, len);
+ return TRUE;
+}
+
+METHOD(tls_reader_t, read_data8, bool,
+ private_tls_reader_t *this, chunk_t *res)
+{
+ u_int8_t len;
+
+ if (!read_uint8(this, &len))
+ {
+ return FALSE;
+ }
+ return read_data(this, len, res);
+}
+
+METHOD(tls_reader_t, read_data16, bool,
+ private_tls_reader_t *this, chunk_t *res)
+{
+ u_int16_t len;
+
+ if (!read_uint16(this, &len))
+ {
+ return FALSE;
+ }
+ return read_data(this, len, res);
+}
+
+METHOD(tls_reader_t, read_data24, bool,
+ private_tls_reader_t *this, chunk_t *res)
+{
+ u_int32_t len;
+
+ if (!read_uint24(this, &len))
+ {
+ return FALSE;
+ }
+ return read_data(this, len, res);
+}
+
+METHOD(tls_reader_t, read_data32, bool,
+ private_tls_reader_t *this, chunk_t *res)
+{
+ u_int32_t len;
+
+ if (!read_uint32(this, &len))
+ {
+ return FALSE;
+ }
+ return read_data(this, len, res);
+}
+
+METHOD(tls_reader_t, destroy, void,
+ private_tls_reader_t *this)
+{
+ free(this);
+}
+
+/**
+ * See header
+ */
+tls_reader_t *tls_reader_create(chunk_t data)
+{
+ private_tls_reader_t *this;
+
+ INIT(this,
+ .public = {
+ .remaining = _remaining,
+ .read_uint8 = _read_uint8,
+ .read_uint16 = _read_uint16,
+ .read_uint24 = _read_uint24,
+ .read_uint32 = _read_uint32,
+ .read_data = _read_data,
+ .read_data8 = _read_data8,
+ .read_data16 = _read_data16,
+ .read_data24 = _read_data24,
+ .read_data32 = _read_data32,
+ .destroy = _destroy,
+ },
+ .buf = data,
+ );
+
+ return &this->public;
+}
diff --git a/src/charon/plugins/eap_tls/tls/tls_reader.h b/src/charon/plugins/eap_tls/tls/tls_reader.h
new file mode 100644
index 000000000..9ea4527d6
--- /dev/null
+++ b/src/charon/plugins/eap_tls/tls/tls_reader.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tls_reader tls_reader
+ * @{ @ingroup tls
+ */
+
+#ifndef TLS_READER_H_
+#define TLS_READER_H_
+
+typedef struct tls_reader_t tls_reader_t;
+
+#include <library.h>
+
+/**
+ * TLS record parser.
+ */
+struct tls_reader_t {
+
+ /**
+ * Get the number of remaining bytes.
+ *
+ * @return number of remaining bytes in buffer
+ */
+ u_int32_t (*remaining)(tls_reader_t *this);
+
+ /**
+ * Read a 8-bit integer from the buffer, advance.
+ *
+ * @param res pointer to result
+ * @return TRUE if integer read successfully
+ */
+ bool (*read_uint8)(tls_reader_t *this, u_int8_t *res);
+
+ /**
+ * Read a 16-bit integer from the buffer, advance.
+ *
+ * @param res pointer to result
+ * @return TRUE if integer read successfully
+ */
+ bool (*read_uint16)(tls_reader_t *this, u_int16_t *res);
+
+ /**
+ * Read a 24-bit integer from the buffer, advance.
+ *
+ * @param res pointer to result
+ * @return TRUE if integer read successfully
+ */
+ bool (*read_uint24)(tls_reader_t *this, u_int32_t *res);
+
+ /**
+ * Read a 32-bit integer from the buffer, advance.
+ *
+ * @param res pointer to result
+ * @return TRUE if integer read successfully
+ */
+ bool (*read_uint32)(tls_reader_t *this, u_int32_t *res);
+
+ /**
+ * Read a chunk of len bytes, advance.
+ *
+ * @param len number of bytes to read
+ * @param res pointer to result, not cloned
+ * @return TRUE if data read successfully
+ */
+ bool (*read_data)(tls_reader_t *this, u_int32_t len, chunk_t *res);
+
+ /**
+ * Read a chunk of bytes with a 8-bit length header, advance.
+ *
+ * @param res pointer to result, not cloned
+ * @return TRUE if data read successfully
+ */
+ bool (*read_data8)(tls_reader_t *this, chunk_t *res);
+
+ /**
+ * Read a chunk of bytes with a 16-bit length header, advance.
+ *
+ * @param res pointer to result, not cloned
+ * @return TRUE if data read successfully
+ */
+ bool (*read_data16)(tls_reader_t *this, chunk_t *res);
+
+ /**
+ * Read a chunk of bytes with a 24-bit length header, advance.
+ *
+ * @param res pointer to result, not cloned
+ * @return TRUE if data read successfully
+ */
+ bool (*read_data24)(tls_reader_t *this, chunk_t *res);
+
+ /**
+ * Read a chunk of bytes with a 32-bit length header, advance.
+ *
+ * @param res pointer to result, not cloned
+ * @return TRUE if data read successfully
+ */
+ bool (*read_data32)(tls_reader_t *this, chunk_t *res);
+
+ /**
+ * Destroy a tls_reader_t.
+ */
+ void (*destroy)(tls_reader_t *this);
+};
+
+/**
+ * Create a tls_reader instance.
+ */
+tls_reader_t *tls_reader_create(chunk_t data);
+
+#endif /** tls_reader_H_ @}*/
diff --git a/src/charon/plugins/eap_tls/tls/tls_server.c b/src/charon/plugins/eap_tls/tls/tls_server.c
index 80b0fae62..3a5d00334 100644
--- a/src/charon/plugins/eap_tls/tls/tls_server.c
+++ b/src/charon/plugins/eap_tls/tls/tls_server.c
@@ -42,7 +42,7 @@ struct private_tls_server_t {
METHOD(tls_handshake_t, process, status_t,
- private_tls_server_t *this, tls_handshake_type_t type, chunk_t data)
+ private_tls_server_t *this, tls_handshake_type_t type, tls_reader_t *reader)
{
return NEED_MORE;
}