diff options
Diffstat (limited to 'src/tls')
-rw-r--r-- | src/tls/s_hello.cpp | 10 | ||||
-rw-r--r-- | src/tls/session_ticket.cpp | 17 | ||||
-rw-r--r-- | src/tls/tls_extensions.cpp | 4 | ||||
-rw-r--r-- | src/tls/tls_extensions.h | 2 | ||||
-rw-r--r-- | src/tls/tls_messages.h | 12 | ||||
-rw-r--r-- | src/tls/tls_server.cpp | 92 | ||||
-rw-r--r-- | src/tls/tls_session.cpp | 2 |
7 files changed, 106 insertions, 33 deletions
diff --git a/src/tls/s_hello.cpp b/src/tls/s_hello.cpp index 3e30382f6..4cbc69f30 100644 --- a/src/tls/s_hello.cpp +++ b/src/tls/s_hello.cpp @@ -37,7 +37,8 @@ Server_Hello::Server_Hello(Record_Writer& writer, m_secure_renegotiation(client_has_secure_renegotiation), m_renegotiation_info(reneg_info), m_next_protocol(client_has_npn), - m_next_protocols(next_protocols) + m_next_protocols(next_protocols), + m_supports_session_ticket(c_hello.supports_session_ticket()) { suite = policy.choose_suite( c_hello.ciphersuites(), @@ -66,6 +67,7 @@ Server_Hello::Server_Hello(Record_Writer& writer, size_t max_fragment_size, bool client_has_secure_renegotiation, const MemoryRegion<byte>& reneg_info, + bool client_supports_session_tickets, bool client_has_npn, const std::vector<std::string>& next_protocols, RandomNumberGenerator& rng) : @@ -78,7 +80,8 @@ Server_Hello::Server_Hello(Record_Writer& writer, m_secure_renegotiation(client_has_secure_renegotiation), m_renegotiation_info(reneg_info), m_next_protocol(client_has_npn), - m_next_protocols(next_protocols) + m_next_protocols(next_protocols), + m_supports_session_ticket(client_supports_session_tickets) { hash.update(writer.send(*this)); } @@ -171,6 +174,9 @@ MemoryVector<byte> Server_Hello::serialize() const if(m_next_protocol) extensions.add(new Next_Protocol_Notification(m_next_protocols)); + if(m_supports_session_ticket) + extensions.add(new Session_Ticket()); + buf += extensions.serialize(); return buf; diff --git a/src/tls/session_ticket.cpp b/src/tls/session_ticket.cpp index d209d3dca..47a8a5c32 100644 --- a/src/tls/session_ticket.cpp +++ b/src/tls/session_ticket.cpp @@ -15,6 +15,23 @@ namespace Botan { namespace TLS { +New_Session_Ticket::New_Session_Ticket(Record_Writer& writer, + Handshake_Hash& hash, + const MemoryRegion<byte>& ticket, + u32bit lifetime) : + m_ticket_lifetime_hint(lifetime), + m_ticket(ticket) + { + hash.update(writer.send(*this)); + } + +New_Session_Ticket::New_Session_Ticket(Record_Writer& writer, + Handshake_Hash& hash) : + m_ticket_lifetime_hint(0) + { + hash.update(writer.send(*this)); + } + New_Session_Ticket::New_Session_Ticket(const MemoryRegion<byte>& buf) : m_ticket_lifetime_hint(0) { diff --git a/src/tls/tls_extensions.cpp b/src/tls/tls_extensions.cpp index ae236d0c5..1ca4e3eb4 100644 --- a/src/tls/tls_extensions.cpp +++ b/src/tls/tls_extensions.cpp @@ -504,10 +504,10 @@ Signature_Algorithms::Signature_Algorithms(TLS_Data_Reader& reader, } } -Session_Ticket::Session_Ticket(const TLS_Data_Reader& reader, +Session_Ticket::Session_Ticket(TLS_Data_Reader& reader, u16bit extension_size) { -#warning "can't read session tickets" + m_ticket = reader.get_elem<byte, MemoryVector<byte> >(extension_size); } } diff --git a/src/tls/tls_extensions.h b/src/tls/tls_extensions.h index c2b9091db..6a97d2560 100644 --- a/src/tls/tls_extensions.h +++ b/src/tls/tls_extensions.h @@ -234,7 +234,7 @@ class Session_Ticket : public Extension /** * Deserialize a session ticket */ - Session_Ticket(const TLS_Data_Reader& reader, u16bit extension_size); + Session_Ticket(TLS_Data_Reader& reader, u16bit extension_size); MemoryVector<byte> serialize() const { return m_ticket; } diff --git a/src/tls/tls_messages.h b/src/tls/tls_messages.h index 019dafa69..78cb6f714 100644 --- a/src/tls/tls_messages.h +++ b/src/tls/tls_messages.h @@ -211,6 +211,7 @@ class Server_Hello : public Handshake_Message size_t max_fragment_size, bool client_has_secure_renegotiation, const MemoryRegion<byte>& reneg_info, + bool client_supports_session_tickets, bool client_has_npn, const std::vector<std::string>& next_protocols, RandomNumberGenerator& rng); @@ -229,8 +230,8 @@ class Server_Hello : public Handshake_Message MemoryVector<byte> m_renegotiation_info; bool m_next_protocol; - bool m_supports_session_ticket; std::vector<std::string> m_next_protocols; + bool m_supports_session_ticket; }; /** @@ -473,8 +474,13 @@ class New_Session_Ticket : public Handshake_Message u32bit ticket_lifetime_hint() const { return m_ticket_lifetime_hint; } const MemoryVector<byte>& ticket() const { return m_ticket; } - New_Session_Ticket(const MemoryVector<byte>& ticket, u32bit lifetime = 0) : - m_ticket_lifetime_hint(lifetime), m_ticket(ticket) {} + New_Session_Ticket(Record_Writer& writer, + Handshake_Hash& hash, + const MemoryRegion<byte>& ticket, + u32bit lifetime = 0); + + New_Session_Ticket(Record_Writer& writer, + Handshake_Hash& hash); New_Session_Ticket(const MemoryRegion<byte>& buf); private: diff --git a/src/tls/tls_server.cpp b/src/tls/tls_server.cpp index 874aa064c..7632dfcdd 100644 --- a/src/tls/tls_server.cpp +++ b/src/tls/tls_server.cpp @@ -22,14 +22,31 @@ bool check_for_resume(Session& session_info, Session_Manager& session_manager, Client_Hello* client_hello) { - MemoryVector<byte> client_session_id = client_hello->session_id(); + const MemoryVector<byte>& client_session_id = client_hello->session_id(); + const MemoryVector<byte>& session_ticket = client_hello->session_ticket(); - if(client_session_id.empty()) // not resuming - return false; + if(session_ticket.empty()) + { + if(client_session_id.empty()) // not resuming + return false; - // not found - if(!session_manager.load_from_session_id(client_session_id, session_info)) - return false; + // not found + if(!session_manager.load_from_session_id(client_session_id, session_info)) + return false; + } + else + { + // If a session ticket was sent, ignore client session ID + try + { +#warning fixed key + session_info = Session::decrypt(session_ticket, SymmetricKey("ABCDEF")); + } + catch(std::exception& e) + { + return false; + } + } // wrong version if(client_hello->version() != session_info.version()) @@ -45,14 +62,14 @@ bool check_for_resume(Session& session_info, session_info.compression_method())) return false; - // client sent a different SRP identity (!!!) + // client sent a different SRP identity if(client_hello->srp_identifier() != "") { if(client_hello->srp_identifier() != session_info.srp_identifier()) return false; } - // client sent a different SNI hostname (!!!) + // client sent a different SNI hostname if(client_hello->sni_hostname() != "") { if(client_hello->sni_hostname() != session_info.sni_hostname()) @@ -204,13 +221,14 @@ void Server::process_handshake_msg(Handshake_Type type, state->server_hello = new Server_Hello( writer, state->hash, - session_info.session_id(), + state->client_hello->session_id(), Protocol_Version(session_info.version()), session_info.ciphersuite_code(), session_info.compression_method(), session_info.fragment_size(), secure_renegotiation.supported(), secure_renegotiation.for_server_hello(), + state->client_hello->supports_session_ticket(), state->client_hello->next_protocol_notification(), m_possible_protocols, rng); @@ -225,6 +243,22 @@ void Server::process_handshake_msg(Handshake_Type type, state->keys = Session_Keys(state, session_info.master_secret(), true); + if(!handshake_fn(session_info)) + { + if(state->server_hello->supports_session_ticket()) + state->new_session_ticket = new New_Session_Ticket(writer, state->hash); + else + session_manager.remove_entry(session_info.session_id()); + } + + // Should only send a new ticket if we need too (eg old session) + if(state->server_hello->supports_session_ticket() && !state->new_session_ticket) + { + state->new_session_ticket = + new New_Session_Ticket(writer, state->hash, + session_info.encrypt(SymmetricKey("ABCDEF"), rng)); + } + writer.send(CHANGE_CIPHER_SPEC, 1); writer.activate(SERVER, state->suite, state->keys, @@ -232,8 +266,6 @@ void Server::process_handshake_msg(Handshake_Type type, state->server_finished = new Finished(writer, state, SERVER); - if(!handshake_fn(session_info)) - session_manager.remove_entry(session_info.session_id()); state->set_expected_next(HANDSHAKE_CCS); } @@ -423,20 +455,10 @@ void Server::process_handshake_msg(Handshake_Type type, if(!state->server_finished) { - state->hash.update(type, contents); - - writer.send(CHANGE_CIPHER_SPEC, 1); - - writer.activate(SERVER, state->suite, state->keys, - state->server_hello->compression_method()); - - state->server_finished = new Finished(writer, state, SERVER); - - if(state->client_certs && state->client_verify) - peer_certs = state->client_certs->cert_chain(); - // already sent finished if resuming, so this is a new session + state->hash.update(type, contents); + Session session_info( state->server_hello->session_id(), state->keys.master_secret(), @@ -453,7 +475,29 @@ void Server::process_handshake_msg(Handshake_Type type, ); if(handshake_fn(session_info)) - session_manager.save(session_info); + { + if(state->server_hello->supports_session_ticket()) + { + state->new_session_ticket = + new New_Session_Ticket(writer, state->hash, + session_info.encrypt(SymmetricKey("ABCDEF"), rng)); + } + else + session_manager.save(session_info); + } + + if(state->server_hello->supports_session_ticket() && !state->new_session_ticket) + state->new_session_ticket = new New_Session_Ticket(writer, state->hash); + + writer.send(CHANGE_CIPHER_SPEC, 1); + + writer.activate(SERVER, state->suite, state->keys, + state->server_hello->compression_method()); + + state->server_finished = new Finished(writer, state, SERVER); + + if(state->client_certs && state->client_verify) + peer_certs = state->client_certs->cert_chain(); } secure_renegotiation.update(state->client_finished, diff --git a/src/tls/tls_session.cpp b/src/tls/tls_session.cpp index a9eb8f95c..a41112bf4 100644 --- a/src/tls/tls_session.cpp +++ b/src/tls/tls_session.cpp @@ -147,7 +147,7 @@ Session::encrypt(const SymmetricKey& master_key, "tls.session.cipher-key"); SymmetricKey hmac_key = kdf->derive_key(32, master_key.bits_of(), - "tls.session.hmac-key"); + "tls.session.mac-key"); InitializationVector aes_iv(rng, 16); |