aboutsummaryrefslogtreecommitdiffstats
path: root/src/tls/tls_client.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/tls/tls_client.cpp')
-rw-r--r--src/tls/tls_client.cpp87
1 files changed, 59 insertions, 28 deletions
diff --git a/src/tls/tls_client.cpp b/src/tls/tls_client.cpp
index 2dd30819f..77e87e9bc 100644
--- a/src/tls/tls_client.cpp
+++ b/src/tls/tls_client.cpp
@@ -19,14 +19,14 @@ namespace TLS {
* TLS Client Constructor
*/
Client::Client(std::function<void (const byte[], size_t)> output_fn,
- std::function<void (const byte[], size_t, Alert)> proc_fn,
- std::function<bool (const Session&)> handshake_fn,
- Session_Manager& session_manager,
- Credentials_Manager& creds,
- const Policy& policy,
- RandomNumberGenerator& rng,
- const std::string& hostname,
- std::function<std::string (std::vector<std::string>)> next_protocol) :
+ std::function<void (const byte[], size_t, Alert)> proc_fn,
+ std::function<bool (const Session&)> handshake_fn,
+ Session_Manager& session_manager,
+ Credentials_Manager& creds,
+ const Policy& policy,
+ RandomNumberGenerator& rng,
+ const std::string& hostname,
+ std::function<std::string (std::vector<std::string>)> next_protocol) :
Channel(output_fn, proc_fn, handshake_fn),
policy(policy),
rng(rng),
@@ -35,7 +35,7 @@ Client::Client(std::function<void (const byte[], size_t)> output_fn,
{
writer.set_version(Protocol_Version::SSL_V3);
- state = new Handshake_State;
+ state = new Handshake_State(new Stream_Handshake_Reader);
state->set_expected_next(SERVER_HELLO);
state->client_npn_cb = next_protocol;
@@ -54,6 +54,7 @@ Client::Client(std::function<void (const byte[], size_t)> output_fn,
state->client_hello = new Client_Hello(
writer,
state->hash,
+ policy,
rng,
session_info,
send_npn_request);
@@ -87,7 +88,7 @@ void Client::renegotiate()
if(state)
return; // currently in handshake
- state = new Handshake_State;
+ state = new Handshake_State(new Stream_Handshake_Reader);
state->set_expected_next(SERVER_HELLO);
state->client_hello = new Client_Hello(writer, state->hash, policy, rng,
@@ -112,7 +113,7 @@ void Client::alert_notify(const Alert& alert)
* Process a handshake message
*/
void Client::process_handshake_msg(Handshake_Type type,
- const MemoryRegion<byte>& contents)
+ const MemoryRegion<byte>& contents)
{
if(state == 0)
throw Unexpected_Message("Unexpected handshake message from server");
@@ -135,12 +136,12 @@ void Client::process_handshake_msg(Handshake_Type type,
return;
}
- state->set_expected_next(SERVER_HELLO);
state->client_hello = new Client_Hello(writer, state->hash, policy, rng,
secure_renegotiation.for_client_hello());
-
secure_renegotiation.update(state->client_hello);
+ state->set_expected_next(SERVER_HELLO);
+
return;
}
@@ -173,17 +174,27 @@ void Client::process_handshake_msg(Handshake_Type type,
"Server sent next protocol but we didn't request it");
}
- state->version = state->server_hello->version();
+ if(state->server_hello->supports_session_ticket())
+ {
+ if(!state->client_hello->supports_session_ticket())
+ throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
+ "Server sent session ticket extension but we did not");
+ }
+
+ state->set_version(state->server_hello->version());
- writer.set_version(state->version);
- reader.set_version(state->version);
+ writer.set_version(state->version());
+ reader.set_version(state->version());
secure_renegotiation.update(state->server_hello);
state->suite = Ciphersuite::by_id(state->server_hello->ciphersuite());
- if(!state->server_hello->session_id().empty() &&
- (state->server_hello->session_id() == state->client_hello->session_id()))
+ const bool server_returned_same_session_id =
+ !state->server_hello->session_id().empty() &&
+ (state->server_hello->session_id() == state->client_hello->session_id());
+
+ if(server_returned_same_session_id)
{
// successful resumption
@@ -199,19 +210,22 @@ void Client::process_handshake_msg(Handshake_Type type,
state->resume_master_secret,
true);
- state->set_expected_next(HANDSHAKE_CCS);
+ if(state->server_hello->supports_session_ticket())
+ state->set_expected_next(NEW_SESSION_TICKET);
+ else
+ state->set_expected_next(HANDSHAKE_CCS);
}
else
{
// new session
- if(state->version > state->client_hello->version())
+ if(state->version() > state->client_hello->version())
{
throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
"Client: Server replied with bad version");
}
- if(state->version < policy.min_version())
+ if(state->version() < policy.min_version())
{
throw TLS_Exception(Alert::PROTOCOL_VERSION,
"Client: Server is too old for specified policy");
@@ -288,7 +302,7 @@ void Client::process_handshake_msg(Handshake_Type type,
state->server_kex = new Server_Key_Exchange(contents,
state->suite.kex_algo(),
state->suite.sig_algo(),
- state->version);
+ state->version());
if(state->suite.sig_algo() != "")
{
@@ -302,12 +316,10 @@ void Client::process_handshake_msg(Handshake_Type type,
else if(type == CERTIFICATE_REQUEST)
{
state->set_expected_next(SERVER_HELLO_DONE);
- state->cert_req = new Certificate_Req(contents, state->version);
+ state->cert_req = new Certificate_Req(contents, state->version());
}
else if(type == SERVER_HELLO_DONE)
{
- state->set_expected_next(HANDSHAKE_CCS);
-
state->server_hello_done = new Server_Hello_Done(contents);
if(state->received_handshake_msg(CERTIFICATE_REQUEST))
@@ -364,6 +376,17 @@ void Client::process_handshake_msg(Handshake_Type type,
}
state->client_finished = new Finished(writer, state, CLIENT);
+
+ if(state->server_hello->supports_session_ticket())
+ state->set_expected_next(NEW_SESSION_TICKET);
+ else
+ state->set_expected_next(HANDSHAKE_CCS);
+ }
+ else if(type == NEW_SESSION_TICKET)
+ {
+ state->new_session_ticket = new New_Session_Ticket(contents);
+
+ state->set_expected_next(HANDSHAKE_CCS);
}
else if(type == HANDSHAKE_CCS)
{
@@ -394,8 +417,17 @@ void Client::process_handshake_msg(Handshake_Type type,
state->client_finished = new Finished(writer, state, CLIENT);
}
+ secure_renegotiation.update(state->client_finished, state->server_finished);
+
+ MemoryVector<byte> session_id = state->server_hello->session_id();
+
+ const MemoryRegion<byte>& session_ticket = state->session_ticket();
+
+ if(session_id.empty() && !session_ticket.empty())
+ session_id = make_hello_random(rng);
+
Session session_info(
- state->server_hello->session_id(),
+ session_id,
state->keys.master_secret(),
state->server_hello->version(),
state->server_hello->ciphersuite(),
@@ -404,6 +436,7 @@ void Client::process_handshake_msg(Handshake_Type type,
secure_renegotiation.supported(),
state->server_hello->fragment_size(),
peer_certs,
+ session_ticket,
state->client_hello->sni_hostname(),
""
);
@@ -413,8 +446,6 @@ void Client::process_handshake_msg(Handshake_Type type,
else
session_manager.remove_entry(session_info.session_id());
- secure_renegotiation.update(state->client_finished, state->server_finished);
-
delete state;
state = 0;
handshake_completed = true;