aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlloyd <[email protected]>2012-03-22 18:20:26 +0000
committerlloyd <[email protected]>2012-03-22 18:20:26 +0000
commit4004e38a00f6bf5743af68d47e44f7adf3872d2b (patch)
tree605a6ec635f74221f65fbdfec00467a72f21e975
parent544171d3e20d65f17a1d3955388a8db4f04cfe44 (diff)
Server side handling of session tickets, though currently with a
hard-coded key.
-rw-r--r--src/tls/s_hello.cpp10
-rw-r--r--src/tls/session_ticket.cpp17
-rw-r--r--src/tls/tls_extensions.cpp4
-rw-r--r--src/tls/tls_extensions.h2
-rw-r--r--src/tls/tls_messages.h12
-rw-r--r--src/tls/tls_server.cpp92
-rw-r--r--src/tls/tls_session.cpp2
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);