From 698674c7f3c559ba940d2f3c97beb833b8093980 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Mon, 25 Jan 2010 11:23:59 +0000 Subject: [PATCH] Send a ClientHello to start TLS negotiation --- src/charon/plugins/eap_tls/tls/tls_peer.c | 87 ++++++++++++++++++++++++++++++- 1 file changed, 86 insertions(+), 1 deletion(-) diff --git a/src/charon/plugins/eap_tls/tls/tls_peer.c b/src/charon/plugins/eap_tls/tls/tls_peer.c index 737f9b3..17f19f1 100644 --- a/src/charon/plugins/eap_tls/tls/tls_peer.c +++ b/src/charon/plugins/eap_tls/tls/tls_peer.c @@ -21,6 +21,11 @@ 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. */ @@ -35,6 +40,11 @@ struct private_tls_peer_t { * TLS crypto context */ tls_crypto_t *crypto; + + /** + * State we are in + */ + peer_state_t state; }; METHOD(tls_handshake_t, process, status_t, @@ -43,10 +53,84 @@ METHOD(tls_handshake_t, process, status_t, 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, 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, @@ -68,6 +152,7 @@ tls_peer_t *tls_peer_create(tls_crypto_t *crypto) .build = _build, .destroy = _destroy, }, + .state = STATE_INIT, .crypto = crypto, ); -- 2.7.4