Send a ClientHello to start TLS negotiation
This commit is contained in:
@@ -21,6 +21,11 @@
|
|||||||
|
|
||||||
typedef struct private_tls_peer_t private_tls_peer_t;
|
typedef struct private_tls_peer_t private_tls_peer_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
STATE_INIT,
|
||||||
|
STATE_HELLO_SENT,
|
||||||
|
} peer_state_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private data of an tls_peer_t object.
|
* Private data of an tls_peer_t object.
|
||||||
*/
|
*/
|
||||||
@@ -35,6 +40,11 @@ struct private_tls_peer_t {
|
|||||||
* TLS crypto context
|
* TLS crypto context
|
||||||
*/
|
*/
|
||||||
tls_crypto_t *crypto;
|
tls_crypto_t *crypto;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* State we are in
|
||||||
|
*/
|
||||||
|
peer_state_t state;
|
||||||
};
|
};
|
||||||
|
|
||||||
METHOD(tls_handshake_t, process, status_t,
|
METHOD(tls_handshake_t, process, status_t,
|
||||||
@@ -43,10 +53,84 @@ 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(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, TLS_1_2);
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
static status_t send_hello(private_tls_peer_t *this,
|
||||||
|
tls_handshake_type_t *type, chunk_t *data)
|
||||||
|
{
|
||||||
|
tls_cipher_suite_t *suite;
|
||||||
|
int count;
|
||||||
|
rng_t *rng;
|
||||||
|
|
||||||
|
rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
|
||||||
|
if (!rng)
|
||||||
|
{
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
count = this->crypto->get_cipher_suites(this->crypto, &suite);
|
||||||
|
*data = build_hello(count, suite, rng);
|
||||||
|
*type = TLS_CLIENT_HELLO;
|
||||||
|
free(suite);
|
||||||
|
rng->destroy(rng);
|
||||||
|
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, chunk_t *data)
|
||||||
{
|
{
|
||||||
return INVALID_STATE;
|
switch (this->state)
|
||||||
|
{
|
||||||
|
case STATE_INIT:
|
||||||
|
this->state = STATE_HELLO_SENT;
|
||||||
|
return send_hello(this, type, data);
|
||||||
|
default:
|
||||||
|
return INVALID_STATE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(tls_handshake_t, destroy, void,
|
METHOD(tls_handshake_t, destroy, void,
|
||||||
@@ -68,6 +152,7 @@ tls_peer_t *tls_peer_create(tls_crypto_t *crypto)
|
|||||||
.build = _build,
|
.build = _build,
|
||||||
.destroy = _destroy,
|
.destroy = _destroy,
|
||||||
},
|
},
|
||||||
|
.state = STATE_INIT,
|
||||||
.crypto = crypto,
|
.crypto = crypto,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user