mirror of
https://github.com/strongswan/strongswan.git
synced 2025-12-01 00:00:31 -05:00
Implemented a tls_writer class to simplify TLS data generation
This commit is contained in:
parent
4ef946dd64
commit
3a1640dea1
@ -12,6 +12,7 @@ libstrongswan_eap_tls_la_SOURCES = eap_tls_plugin.h eap_tls_plugin.c \
|
|||||||
tls/tls_fragmentation.h tls/tls_fragmentation.c \
|
tls/tls_fragmentation.h tls/tls_fragmentation.c \
|
||||||
tls/tls_crypto.h tls/tls_crypto.c \
|
tls/tls_crypto.h tls/tls_crypto.c \
|
||||||
tls/tls_reader.h tls/tls_reader.c \
|
tls/tls_reader.h tls/tls_reader.c \
|
||||||
|
tls/tls_writer.h tls/tls_writer.c \
|
||||||
tls/tls_peer.h tls/tls_peer.c \
|
tls/tls_peer.h tls/tls_peer.c \
|
||||||
tls/tls_server.h tls/tls_server.c \
|
tls/tls_server.h tls/tls_server.c \
|
||||||
tls/tls_handshake.h
|
tls/tls_handshake.h
|
||||||
|
|||||||
@ -50,6 +50,11 @@ struct private_tls_fragmentation_t {
|
|||||||
* Currently processed handshake message type
|
* Currently processed handshake message type
|
||||||
*/
|
*/
|
||||||
tls_handshake_type_t type;
|
tls_handshake_type_t type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handshake output buffer
|
||||||
|
*/
|
||||||
|
chunk_t output;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -62,15 +67,6 @@ struct private_tls_fragmentation_t {
|
|||||||
*/
|
*/
|
||||||
#define MAX_TLS_HANDSHAKE_LEN 65536
|
#define MAX_TLS_HANDSHAKE_LEN 65536
|
||||||
|
|
||||||
/**
|
|
||||||
* TLS handshake message header
|
|
||||||
*/
|
|
||||||
typedef union {
|
|
||||||
u_int8_t type;
|
|
||||||
/* 24bit length field */
|
|
||||||
u_int32_t length;
|
|
||||||
} tls_handshake_header_t;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process TLS handshake protocol data
|
* Process TLS handshake protocol data
|
||||||
*/
|
*/
|
||||||
@ -171,27 +167,61 @@ METHOD(tls_fragmentation_t, process, status_t,
|
|||||||
METHOD(tls_fragmentation_t, build, status_t,
|
METHOD(tls_fragmentation_t, build, status_t,
|
||||||
private_tls_fragmentation_t *this, tls_content_type_t *type, chunk_t *data)
|
private_tls_fragmentation_t *this, tls_content_type_t *type, chunk_t *data)
|
||||||
{
|
{
|
||||||
tls_handshake_header_t header;
|
|
||||||
tls_handshake_type_t hs_type;
|
tls_handshake_type_t hs_type;
|
||||||
chunk_t hs_data;
|
tls_writer_t *writer, *msg;
|
||||||
status_t status;
|
status_t status;
|
||||||
|
|
||||||
status = this->handshake->build(this->handshake, &hs_type, &hs_data);
|
if (!this->output.len)
|
||||||
if (status != NEED_MORE)
|
{
|
||||||
|
msg = tls_writer_create(64);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
writer = tls_writer_create(64);
|
||||||
|
status = this->handshake->build(this->handshake, &hs_type, writer);
|
||||||
|
switch (status)
|
||||||
|
{
|
||||||
|
case NEED_MORE:
|
||||||
|
msg->write_uint8(msg, hs_type);
|
||||||
|
msg->write_data24(msg, writer->get_buf(writer));
|
||||||
|
break;
|
||||||
|
case INVALID_STATE:
|
||||||
|
this->output = chunk_clone(msg->get_buf(msg));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
writer->destroy(writer);
|
||||||
|
}
|
||||||
|
while (status == NEED_MORE);
|
||||||
|
|
||||||
|
msg->destroy(msg);
|
||||||
|
if (status != INVALID_STATE)
|
||||||
{
|
{
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
htoun32(&header.length, hs_data.len);
|
}
|
||||||
header.type |= hs_type;
|
|
||||||
*data = chunk_cat("cm", chunk_from_thing(header), hs_data);
|
if (this->output.len)
|
||||||
|
{
|
||||||
*type = TLS_HANDSHAKE;
|
*type = TLS_HANDSHAKE;
|
||||||
|
if (this->output.len <= MAX_TLS_FRAGMENT_LEN)
|
||||||
|
{
|
||||||
|
*data = this->output;
|
||||||
|
this->output = chunk_empty;
|
||||||
return NEED_MORE;
|
return NEED_MORE;
|
||||||
|
}
|
||||||
|
*data = chunk_create(this->output.ptr, MAX_TLS_FRAGMENT_LEN);
|
||||||
|
this->output = chunk_clone(chunk_skip(this->output, MAX_TLS_FRAGMENT_LEN));
|
||||||
|
return NEED_MORE;
|
||||||
|
}
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(tls_fragmentation_t, destroy, void,
|
METHOD(tls_fragmentation_t, destroy, void,
|
||||||
private_tls_fragmentation_t *this)
|
private_tls_fragmentation_t *this)
|
||||||
{
|
{
|
||||||
free(this->input.ptr);
|
free(this->input.ptr);
|
||||||
|
free(this->output.ptr);
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -25,6 +25,7 @@ typedef struct tls_handshake_t tls_handshake_t;
|
|||||||
|
|
||||||
#include "tls.h"
|
#include "tls.h"
|
||||||
#include "tls_reader.h"
|
#include "tls_reader.h"
|
||||||
|
#include "tls_writer.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TLS handshake state machine interface.
|
* TLS handshake state machine interface.
|
||||||
@ -48,7 +49,7 @@ struct tls_handshake_t {
|
|||||||
* Build TLS handshake messages to send out.
|
* Build TLS handshake messages to send out.
|
||||||
*
|
*
|
||||||
* @param type type of created handshake message
|
* @param type type of created handshake message
|
||||||
* @param data allocated TLS handshake message data
|
* @param writer TLS data buffer to write to
|
||||||
* @return
|
* @return
|
||||||
* - SUCCESS if handshake complete
|
* - SUCCESS if handshake complete
|
||||||
* - FAILED if handshake failed
|
* - FAILED if handshake failed
|
||||||
@ -56,7 +57,7 @@ struct tls_handshake_t {
|
|||||||
* - INVALID_STATE if more input to process() required
|
* - INVALID_STATE if more input to process() required
|
||||||
*/
|
*/
|
||||||
status_t (*build)(tls_handshake_t *this,
|
status_t (*build)(tls_handshake_t *this,
|
||||||
tls_handshake_type_t *type, chunk_t *data);
|
tls_handshake_type_t *type, tls_writer_t *writer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy a tls_handshake_t.
|
* Destroy a tls_handshake_t.
|
||||||
|
|||||||
@ -185,82 +185,54 @@ METHOD(tls_handshake_t, process, status_t,
|
|||||||
return NEED_MORE;
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Build the Client Hello using a given set of ciphers
|
|
||||||
*/
|
|
||||||
static chunk_t build_hello(private_tls_peer_t *this,
|
|
||||||
int count, tls_cipher_suite_t *suite, rng_t *rng)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
struct __attribute__((packed)) {
|
|
||||||
u_int16_t version;
|
|
||||||
struct __attribute__((packed)) {
|
|
||||||
u_int32_t gmt;
|
|
||||||
u_int8_t bytes[28];
|
|
||||||
} random;
|
|
||||||
struct __attribute__((packed)) {
|
|
||||||
/* never send a session identifier */
|
|
||||||
u_int8_t len;
|
|
||||||
u_int8_t id[0];
|
|
||||||
} session;
|
|
||||||
struct __attribute__((packed)) {
|
|
||||||
u_int16_t len;
|
|
||||||
u_int16_t suite[count];
|
|
||||||
} cipher;
|
|
||||||
struct __attribute__((packed)) {
|
|
||||||
/* currently NULL compression only */
|
|
||||||
u_int8_t len;
|
|
||||||
u_int8_t method[1];
|
|
||||||
} compression;
|
|
||||||
u_int8_t extensions[0];
|
|
||||||
} hello;
|
|
||||||
|
|
||||||
htoun16(&hello.session.len, 0);
|
|
||||||
htoun16(&hello.version, this->tls->get_version(this->tls));
|
|
||||||
htoun32(&hello.random.gmt, time(NULL));
|
|
||||||
rng->get_bytes(rng, sizeof(hello.random.bytes), (char*)&hello.random.bytes);
|
|
||||||
htoun16(&hello.cipher.len, count * 2);
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
htoun16(&hello.cipher.suite[i], suite[i]);
|
|
||||||
}
|
|
||||||
hello.compression.len = 1;
|
|
||||||
hello.compression.method[0] = 0;
|
|
||||||
return chunk_clone(chunk_create((char*)&hello, sizeof(hello)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a client hello
|
* Send a client hello
|
||||||
*/
|
*/
|
||||||
static status_t send_hello(private_tls_peer_t *this,
|
static status_t send_hello(private_tls_peer_t *this,
|
||||||
tls_handshake_type_t *type, chunk_t *data)
|
tls_handshake_type_t *type, tls_writer_t *writer)
|
||||||
{
|
{
|
||||||
tls_cipher_suite_t *suite;
|
tls_cipher_suite_t *suite;
|
||||||
int count;
|
int count, i;
|
||||||
rng_t *rng;
|
rng_t *rng;
|
||||||
|
char random[28];
|
||||||
|
|
||||||
rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
|
rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
|
||||||
if (!rng)
|
if (!rng)
|
||||||
{
|
{
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
count = this->crypto->get_cipher_suites(this->crypto, &suite);
|
rng->get_bytes(rng, sizeof(random), random);
|
||||||
*data = build_hello(this, count, suite, rng);
|
|
||||||
*type = TLS_CLIENT_HELLO;
|
|
||||||
free(suite);
|
|
||||||
rng->destroy(rng);
|
rng->destroy(rng);
|
||||||
|
|
||||||
|
writer->write_uint16(writer, this->tls->get_version(this->tls));
|
||||||
|
writer->write_uint32(writer, time(NULL));
|
||||||
|
writer->write_data(writer, chunk_from_thing(random));
|
||||||
|
/* session identifier => none */
|
||||||
|
writer->write_data8(writer, chunk_empty);
|
||||||
|
|
||||||
|
count = this->crypto->get_cipher_suites(this->crypto, &suite);
|
||||||
|
writer->write_uint16(writer, count * 2);
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
writer->write_uint16(writer, suite[i]);
|
||||||
|
}
|
||||||
|
free(suite);
|
||||||
|
/* NULL compression only */
|
||||||
|
writer->write_uint8(writer, 1);
|
||||||
|
writer->write_uint8(writer, 0);
|
||||||
|
|
||||||
|
*type = TLS_CLIENT_HELLO;
|
||||||
this->state = STATE_HELLO_SENT;
|
this->state = STATE_HELLO_SENT;
|
||||||
return NEED_MORE;
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(tls_handshake_t, build, status_t,
|
METHOD(tls_handshake_t, build, 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_writer_t *writer)
|
||||||
{
|
{
|
||||||
switch (this->state)
|
switch (this->state)
|
||||||
{
|
{
|
||||||
case STATE_INIT:
|
case STATE_INIT:
|
||||||
return send_hello(this, type, data);
|
return send_hello(this, type, writer);
|
||||||
default:
|
default:
|
||||||
return INVALID_STATE;
|
return INVALID_STATE;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,7 +48,7 @@ METHOD(tls_handshake_t, process, status_t,
|
|||||||
}
|
}
|
||||||
|
|
||||||
METHOD(tls_handshake_t, build, status_t,
|
METHOD(tls_handshake_t, build, 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_writer_t *writer)
|
||||||
{
|
{
|
||||||
return INVALID_STATE;
|
return INVALID_STATE;
|
||||||
}
|
}
|
||||||
|
|||||||
237
src/charon/plugins/eap_tls/tls/tls_writer.c
Normal file
237
src/charon/plugins/eap_tls/tls/tls_writer.c
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
/*
|
||||||
|
* 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_writer.h"
|
||||||
|
|
||||||
|
typedef struct private_tls_writer_t private_tls_writer_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private data of an tls_writer_t object.
|
||||||
|
*/
|
||||||
|
struct private_tls_writer_t {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public tls_writer_t interface.
|
||||||
|
*/
|
||||||
|
tls_writer_t public;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocated buffer
|
||||||
|
*/
|
||||||
|
chunk_t buf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used bytes in buffer
|
||||||
|
*/
|
||||||
|
size_t used;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of bytes to increase buffer size
|
||||||
|
*/
|
||||||
|
size_t increase;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increase buffer size
|
||||||
|
*/
|
||||||
|
static void increase(private_tls_writer_t *this)
|
||||||
|
{
|
||||||
|
this->buf.len += this->increase;
|
||||||
|
this->buf.ptr = realloc(this->buf.ptr, this->buf.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(tls_writer_t, write_uint8, void,
|
||||||
|
private_tls_writer_t *this, u_int8_t value)
|
||||||
|
{
|
||||||
|
if (this->used + 1 > this->buf.len)
|
||||||
|
{
|
||||||
|
increase(this);
|
||||||
|
}
|
||||||
|
this->buf.ptr[this->used] = value;
|
||||||
|
this->used += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(tls_writer_t, write_uint16, void,
|
||||||
|
private_tls_writer_t *this, u_int16_t value)
|
||||||
|
{
|
||||||
|
if (this->used + 2 > this->buf.len)
|
||||||
|
{
|
||||||
|
increase(this);
|
||||||
|
}
|
||||||
|
htoun16(this->buf.ptr + this->used, value);
|
||||||
|
this->used += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(tls_writer_t, write_uint24, void,
|
||||||
|
private_tls_writer_t *this, u_int32_t value)
|
||||||
|
{
|
||||||
|
if (this->used + 3 > this->buf.len)
|
||||||
|
{
|
||||||
|
increase(this);
|
||||||
|
}
|
||||||
|
value = htonl(value);
|
||||||
|
memcpy(this->buf.ptr + this->used, ((char*)&value) + 1, 3);
|
||||||
|
this->used += 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(tls_writer_t, write_uint32, void,
|
||||||
|
private_tls_writer_t *this, u_int32_t value)
|
||||||
|
{
|
||||||
|
if (this->used + 4 > this->buf.len)
|
||||||
|
{
|
||||||
|
increase(this);
|
||||||
|
}
|
||||||
|
htoun32(this->buf.ptr + this->used, value);
|
||||||
|
this->used += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(tls_writer_t, write_data, void,
|
||||||
|
private_tls_writer_t *this, chunk_t value)
|
||||||
|
{
|
||||||
|
while (this->used + value.len > this->buf.len)
|
||||||
|
{
|
||||||
|
increase(this);
|
||||||
|
}
|
||||||
|
memcpy(this->buf.ptr + this->used, value.ptr, value.len);
|
||||||
|
this->used += value.len;
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(tls_writer_t, write_data8, void,
|
||||||
|
private_tls_writer_t *this, chunk_t value)
|
||||||
|
{
|
||||||
|
write_uint8(this, value.len);
|
||||||
|
write_data(this, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(tls_writer_t, write_data16, void,
|
||||||
|
private_tls_writer_t *this, chunk_t value)
|
||||||
|
{
|
||||||
|
write_uint16(this, value.len);
|
||||||
|
write_data(this, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(tls_writer_t, write_data24, void,
|
||||||
|
private_tls_writer_t *this, chunk_t value)
|
||||||
|
{
|
||||||
|
write_uint24(this, value.len);
|
||||||
|
write_data(this, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(tls_writer_t, write_data32, void,
|
||||||
|
private_tls_writer_t *this, chunk_t value)
|
||||||
|
{
|
||||||
|
write_uint32(this, value.len);
|
||||||
|
write_data(this, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(tls_writer_t, wrap8, void,
|
||||||
|
private_tls_writer_t *this)
|
||||||
|
{
|
||||||
|
if (this->used + 1 > this->buf.len)
|
||||||
|
{
|
||||||
|
increase(this);
|
||||||
|
}
|
||||||
|
memmove(this->buf.ptr + 1, this->buf.ptr, 1);
|
||||||
|
this->buf.ptr[0] = this->used;
|
||||||
|
this->used += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(tls_writer_t, wrap16, void,
|
||||||
|
private_tls_writer_t *this)
|
||||||
|
{
|
||||||
|
if (this->used + 2 > this->buf.len)
|
||||||
|
{
|
||||||
|
increase(this);
|
||||||
|
}
|
||||||
|
memmove(this->buf.ptr + 2, this->buf.ptr, 2);
|
||||||
|
htoun16(this->buf.ptr, this->used);
|
||||||
|
this->used += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(tls_writer_t, wrap24, void,
|
||||||
|
private_tls_writer_t *this)
|
||||||
|
{
|
||||||
|
u_int32_t len;
|
||||||
|
|
||||||
|
if (this->used + 3 > this->buf.len)
|
||||||
|
{
|
||||||
|
increase(this);
|
||||||
|
}
|
||||||
|
memmove(this->buf.ptr + 3, this->buf.ptr, 3);
|
||||||
|
|
||||||
|
len = htonl(this->used);
|
||||||
|
memcpy(this->buf.ptr, ((char*)&len) + 1, 3);
|
||||||
|
this->used += 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(tls_writer_t, wrap32, void,
|
||||||
|
private_tls_writer_t *this)
|
||||||
|
{
|
||||||
|
if (this->used + 4 > this->buf.len)
|
||||||
|
{
|
||||||
|
increase(this);
|
||||||
|
}
|
||||||
|
memmove(this->buf.ptr + 4, this->buf.ptr, 4);
|
||||||
|
htoun32(this->buf.ptr, this->used);
|
||||||
|
this->used += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(tls_writer_t, get_buf, chunk_t,
|
||||||
|
private_tls_writer_t *this)
|
||||||
|
{
|
||||||
|
return chunk_create(this->buf.ptr, this->used);
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(tls_writer_t, destroy, void,
|
||||||
|
private_tls_writer_t *this)
|
||||||
|
{
|
||||||
|
free(this->buf.ptr);
|
||||||
|
free(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See header
|
||||||
|
*/
|
||||||
|
tls_writer_t *tls_writer_create(u_int32_t bufsize)
|
||||||
|
{
|
||||||
|
private_tls_writer_t *this;
|
||||||
|
|
||||||
|
INIT(this,
|
||||||
|
.public = {
|
||||||
|
.write_uint8 = _write_uint8,
|
||||||
|
.write_uint16 = _write_uint16,
|
||||||
|
.write_uint24 = _write_uint24,
|
||||||
|
.write_uint32 = _write_uint32,
|
||||||
|
.write_data = _write_data,
|
||||||
|
.write_data8 = _write_data8,
|
||||||
|
.write_data16 = _write_data16,
|
||||||
|
.write_data24 = _write_data24,
|
||||||
|
.write_data32 = _write_data32,
|
||||||
|
.wrap8 = _wrap8,
|
||||||
|
.wrap16 = _wrap16,
|
||||||
|
.wrap24 = _wrap24,
|
||||||
|
.wrap32 = _wrap32,
|
||||||
|
.get_buf = _get_buf,
|
||||||
|
.destroy = _destroy,
|
||||||
|
},
|
||||||
|
.increase = bufsize ?: 32,
|
||||||
|
);
|
||||||
|
if (bufsize)
|
||||||
|
{
|
||||||
|
this->buf = chunk_alloc(bufsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
return &this->public;
|
||||||
|
}
|
||||||
136
src/charon/plugins/eap_tls/tls/tls_writer.h
Normal file
136
src/charon/plugins/eap_tls/tls/tls_writer.h
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
/*
|
||||||
|
* 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_writer tls_writer
|
||||||
|
* @{ @ingroup tls
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TLS_WRITER_H_
|
||||||
|
#define TLS_WRITER_H_
|
||||||
|
|
||||||
|
typedef struct tls_writer_t tls_writer_t;
|
||||||
|
|
||||||
|
#include <library.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TLS record generator.
|
||||||
|
*/
|
||||||
|
struct tls_writer_t {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append a 8-bit integer to the buffer.
|
||||||
|
*
|
||||||
|
* @param value value to append
|
||||||
|
*/
|
||||||
|
void (*write_uint8)(tls_writer_t *this, u_int8_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append a 16-bit integer to the buffer.
|
||||||
|
*
|
||||||
|
* @param value value to append
|
||||||
|
*/
|
||||||
|
void (*write_uint16)(tls_writer_t *this, u_int16_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append a 24-bit integer to the buffer.
|
||||||
|
*
|
||||||
|
* @param value value to append
|
||||||
|
*/
|
||||||
|
void (*write_uint24)(tls_writer_t *this, u_int32_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append a 32-bit integer to the buffer.
|
||||||
|
*
|
||||||
|
* @param value value to append
|
||||||
|
*/
|
||||||
|
void (*write_uint32)(tls_writer_t *this, u_int32_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append a chunk of data without a length header.
|
||||||
|
*
|
||||||
|
* @param value value to append
|
||||||
|
*/
|
||||||
|
void (*write_data)(tls_writer_t *this, chunk_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append a chunk of data with a 16-bit length header.
|
||||||
|
*
|
||||||
|
* @param value value to append
|
||||||
|
*/
|
||||||
|
void (*write_data8)(tls_writer_t *this, chunk_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append a chunk of data with a 8-bit length header.
|
||||||
|
*
|
||||||
|
* @param value value to append
|
||||||
|
*/
|
||||||
|
void (*write_data16)(tls_writer_t *this, chunk_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append a chunk of data with a 24-bit length header.
|
||||||
|
*
|
||||||
|
* @param value value to append
|
||||||
|
*/
|
||||||
|
void (*write_data24)(tls_writer_t *this, chunk_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append a chunk of data with a 32-bit length header.
|
||||||
|
*
|
||||||
|
* @param value value to append
|
||||||
|
*/
|
||||||
|
void (*write_data32)(tls_writer_t *this, chunk_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepend a 8-bit length header to existing data.
|
||||||
|
*/
|
||||||
|
void (*wrap8)(tls_writer_t *this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepend a 16-bit length header to existing data.
|
||||||
|
*/
|
||||||
|
void (*wrap16)(tls_writer_t *this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepend a 24-bit length header to existing data.
|
||||||
|
*/
|
||||||
|
void (*wrap24)(tls_writer_t *this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepend a 32-bit length header to existing data.
|
||||||
|
*/
|
||||||
|
void (*wrap32)(tls_writer_t *this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the encoded data buffer.
|
||||||
|
*
|
||||||
|
* @return chunk to internal buffer
|
||||||
|
*/
|
||||||
|
chunk_t (*get_buf)(tls_writer_t *this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy a tls_writer_t.
|
||||||
|
*/
|
||||||
|
void (*destroy)(tls_writer_t *this);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a tls_writer instance.
|
||||||
|
*
|
||||||
|
* @param bufsize initially allocated buffer size
|
||||||
|
*/
|
||||||
|
tls_writer_t *tls_writer_create(u_int32_t bufsize);
|
||||||
|
|
||||||
|
#endif /** TLS_WRITER_H_ @}*/
|
||||||
Loading…
x
Reference in New Issue
Block a user