Pass TLS records to newly introduced TLS stack

This commit is contained in:
Martin Willi
2010-08-03 15:39:24 +02:00
parent f7f63c52e1
commit dcbbeb2d09
3 changed files with 158 additions and 11 deletions
+55 -11
View File
@@ -15,6 +15,8 @@
#include "eap_tls.h"
#include "tls/tls.h"
#include <daemon.h>
#include <library.h>
@@ -45,6 +47,11 @@ struct private_eap_tls_t {
*/
bool is_server;
/**
* TLS layers
*/
tls_t *tls;
/**
* Allocated input buffer
*/
@@ -212,28 +219,62 @@ static eap_payload_t *read_buf(private_eap_tls_t *this, u_int8_t identifier)
*/
static status_t process_buf(private_eap_tls_t *this)
{
tls_record_t *record;
chunk_t input;
tls_record_t *in, out;
chunk_t data;
u_int16_t len;
status_t status;
input = this->input;
while (input.len > sizeof(tls_record_t))
/* pass input buffer to upper layer, record for record */
data = this->input;
while (data.len > sizeof(tls_record_t))
{
record = (tls_record_t*)input.ptr;
len = untoh16(&record->length);
if (len > input.len)
in = (tls_record_t*)data.ptr;
len = untoh16(&in->length);
if (len > data.len - sizeof(tls_record_t))
{
DBG1(DBG_IKE, "TLS record length invalid");
break;
}
/* TODO: pass record to next layer */
input = chunk_skip(input, len);
status = this->tls->process(this->tls, in->type,
chunk_create(in->data, len));
if (status != NEED_MORE)
{
return status;
}
data = chunk_skip(data, len + sizeof(tls_record_t));
}
chunk_free(&this->input);
this->inpos = 0;
/* TODO: read records from next layer */
return NEED_MORE;
/* read in records from upper layer, append to output buffer */
chunk_free(&this->output);
while (TRUE)
{
tls_content_type_t type;
chunk_t header = chunk_from_thing(out);
status = this->tls->build(this->tls, &type, &data);
switch (status)
{
case INVALID_STATE:
/* invalid state means we need more input from peer first */
return NEED_MORE;
case NEED_MORE:
case SUCCESS:
break;
case FAILED:
default:
return FAILED;
}
out.type = type;
htoun16(&out.version, TLS_1_2);
htoun16(&out.length, data.len);
this->output = chunk_cat("mcm", this->output, header, data);
if (status == SUCCESS)
{
return SUCCESS;
}
}
}
METHOD(eap_method_t, process, status_t,
@@ -309,6 +350,8 @@ METHOD(eap_method_t, destroy, void,
free(this->input.ptr);
free(this->output.ptr);
this->tls->destroy(this->tls);
free(this);
}
@@ -332,6 +375,7 @@ static eap_tls_t *eap_tls_create(identification_t *server,
.peer = peer->clone(peer),
.server = server->clone(server),
.is_server = is_server,
.tls = tls_create(is_server),
);
return &this->public;
+58
View File
@@ -15,6 +15,8 @@
#include "tls.h"
#include <daemon.h>
ENUM(tls_version_names, SSL_2_0, TLS_1_2,
"SSLv2",
"SSLv3",
@@ -44,3 +46,59 @@ ENUM_NEXT(tls_handshake_type_names, TLS_CERTIFICATE, TLS_CLIENT_KEY_EXCHANGE, TL
ENUM_NEXT(tls_handshake_type_names, TLS_FINISHED, TLS_FINISHED, TLS_CLIENT_KEY_EXCHANGE,
"Finished");
ENUM_END(tls_handshake_type_names, TLS_FINISHED);
typedef struct private_tls_t private_tls_t;
/**
* Private data of an tls_protection_t object.
*/
struct private_tls_t {
/**
* Public tls_t interface.
*/
tls_t public;
/**
* Role this TLS stack acts as.
*/
bool is_server;
};
METHOD(tls_t, process, status_t,
private_tls_t *this, tls_content_type_t type, chunk_t data)
{
return NEED_MORE;
}
METHOD(tls_t, build, status_t,
private_tls_t *this, tls_content_type_t *type, chunk_t *data)
{
return INVALID_STATE;
}
METHOD(tls_t, destroy, void,
private_tls_t *this)
{
free(this);
}
/**
* See header
*/
tls_t *tls_create(bool is_server)
{
private_tls_t *this;
INIT(this,
.public = {
.process = _process,
.build = _build,
.destroy = _destroy,
},
.is_server = is_server,
);
return &this->public;
}
+45
View File
@@ -28,6 +28,7 @@ typedef enum tls_version_t tls_version_t;
typedef enum tls_content_type_t tls_content_type_t;
typedef enum tls_handshake_type_t tls_handshake_type_t;
typedef enum tls_cipher_suite_t tls_cipher_suite_t;
typedef struct tls_t tls_t;
#include <library.h>
@@ -123,4 +124,48 @@ enum tls_cipher_suite_t {
TLS_DH_ANON_WITH_AES_256_CBC_SHA256 = 0x6D,
};
/**
* A bottom-up driven TLS stack, suitable for EAP implementations.
*/
struct tls_t {
/**
* Process a TLS record, pass it to upper layers.
*
* @param type type of the TLS record to process
* @param data associated TLS record data
* @return
* - SUCCESS if TLS negotiation complete
* - FAILED if TLS handshake failed
* - NEED_MORE if more invocations to process/build needed
*/
status_t (*process)(tls_t *this, tls_content_type_t type, chunk_t data);
/**
* Query upper layer for TLS record, build protected record.
*
* @param type type of the built TLS record
* @param data allocated data of the built TLS record
* @return
* - SUCCESS if TLS negotiation complete
* - FAILED if TLS handshake failed
* - NEED_MORE if upper layers have more records to send
* - INVALID_STATE if more input records required
*/
status_t (*build)(tls_t *this, tls_content_type_t *type, chunk_t *data);
/**
* Destroy a tls_t.
*/
void (*destroy)(tls_t *this);
};
/**
* Create a tls instance.
*
* @param is_server TRUE to act as server, FALSE for client
* @return TLS stack
*/
tls_t *tls_create(bool is_server);
#endif /** TLS_H_ @}*/