aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/tls/c_hello.cpp (renamed from src/tls/hello.cpp)180
-rw-r--r--src/tls/info.txt17
-rw-r--r--src/tls/s_hello.cpp201
-rw-r--r--src/tls/tls_extensions.cpp4
-rw-r--r--src/tls/tls_messages.h22
-rw-r--r--src/tls/tls_server.cpp49
-rw-r--r--src/tls/tls_server.h19
-rw-r--r--src/tls/tls_session_manager.cpp2
8 files changed, 271 insertions, 223 deletions
diff --git a/src/tls/hello.cpp b/src/tls/c_hello.cpp
index 8c13cb8f6..3164f30ee 100644
--- a/src/tls/hello.cpp
+++ b/src/tls/c_hello.cpp
@@ -1,5 +1,5 @@
;/*
-* TLS Hello Messages
+* TLS Hello Request and Client Hello Messages
* (C) 2004-2011 Jack Lloyd
*
* Released under the terms of the Botan license
@@ -287,182 +287,4 @@ bool Client_Hello::offered_suite(u16bit ciphersuite) const
return false;
}
-/*
-* Create a new Server Hello message
-*/
-Server_Hello::Server_Hello(Record_Writer& writer,
- TLS_Handshake_Hash& hash,
- const TLS_Policy& policy,
- RandomNumberGenerator& rng,
- bool client_has_secure_renegotiation,
- const MemoryRegion<byte>& reneg_info,
- const std::vector<X509_Certificate>& certs,
- const Client_Hello& c_hello,
- Version_Code ver) :
- s_version(ver),
- m_session_id(rng.random_vec(32)),
- s_random(rng.random_vec(32)),
- m_fragment_size(c_hello.fragment_size()),
- m_secure_renegotiation(client_has_secure_renegotiation),
- m_renegotiation_info(reneg_info),
- m_next_protocol(false)
- {
- bool have_rsa = false, have_dsa = false;
-
- for(size_t i = 0; i != certs.size(); ++i)
- {
- Public_Key* key = certs[i].subject_public_key();
- if(key->algo_name() == "RSA")
- have_rsa = true;
-
- if(key->algo_name() == "DSA")
- have_dsa = true;
- }
-
- suite = policy.choose_suite(c_hello.ciphersuites(), have_rsa, have_dsa, false);
-
- if(suite == 0)
- throw TLS_Exception(HANDSHAKE_FAILURE,
- "Can't agree on a ciphersuite with client");
-
- comp_method = policy.choose_compression(c_hello.compression_methods());
-
- send(writer, hash);
- }
-
-/*
-* Create a new Server Hello message
-*/
-Server_Hello::Server_Hello(Record_Writer& writer,
- TLS_Handshake_Hash& hash,
- RandomNumberGenerator& rng,
- bool client_has_secure_renegotiation,
- const MemoryRegion<byte>& reneg_info,
- const MemoryRegion<byte>& session_id,
- size_t fragment_size,
- u16bit ciphersuite,
- byte compression,
- Version_Code ver) :
- s_version(ver),
- m_session_id(session_id),
- s_random(rng.random_vec(32)),
- suite(ciphersuite),
- comp_method(compression),
- m_fragment_size(fragment_size),
- m_secure_renegotiation(client_has_secure_renegotiation),
- m_renegotiation_info(reneg_info),
- m_next_protocol(false)
- {
- send(writer, hash);
- }
-
-/*
-* Serialize a Server Hello message
-*/
-MemoryVector<byte> Server_Hello::serialize() const
- {
- MemoryVector<byte> buf;
-
- buf.push_back(static_cast<byte>(s_version >> 8));
- buf.push_back(static_cast<byte>(s_version ));
- buf += s_random;
-
- append_tls_length_value(buf, m_session_id, 1);
-
- buf.push_back(get_byte(0, suite));
- buf.push_back(get_byte(1, suite));
-
- buf.push_back(comp_method);
-
- TLS_Extensions extensions;
-
- if(m_secure_renegotiation)
- extensions.push_back(new Renegotation_Extension(m_renegotiation_info));
-
- if(m_fragment_size != 0)
- extensions.push_back(new Maximum_Fragment_Length(m_fragment_size));
-
- if(m_next_protocol)
- extensions.push_back(new Next_Protocol_Negotiation(m_next_protocols));
-
- buf += extensions.serialize();
-
- return buf;
- }
-
-/*
-* Deserialize a Server Hello message
-*/
-void Server_Hello::deserialize(const MemoryRegion<byte>& buf)
- {
- m_secure_renegotiation = false;
- m_next_protocol = false;
-
- if(buf.size() < 38)
- throw Decoding_Error("Server_Hello: Packet corrupted");
-
- TLS_Data_Reader reader(buf);
-
- s_version = static_cast<Version_Code>(reader.get_u16bit());
-
- if(s_version != SSL_V3 && s_version != TLS_V10 && s_version != TLS_V11)
- {
- throw TLS_Exception(PROTOCOL_VERSION,
- "Server_Hello: Unsupported server version");
- }
-
- s_random = reader.get_fixed<byte>(32);
-
- m_session_id = reader.get_range<byte>(1, 0, 32);
-
- suite = reader.get_u16bit();
-
- comp_method = reader.get_byte();
-
- TLS_Extensions extensions(reader);
-
- for(size_t i = 0; i != extensions.count(); ++i)
- {
- TLS_Extension* extn = extensions.at(i);
-
- if(Renegotation_Extension* reneg = dynamic_cast<Renegotation_Extension*>(extn))
- {
- // checked by TLS_Client / TLS_Server as they know the handshake state
- m_secure_renegotiation = true;
- m_renegotiation_info = reneg->renegotiation_info();
- }
- else if(Next_Protocol_Negotiation* npn = dynamic_cast<Next_Protocol_Negotiation*>(extn))
- {
- m_next_protocols = npn->protocols();
- m_next_protocol = true;
- }
- }
- }
-
-/*
-* Create a new Server Hello Done message
-*/
-Server_Hello_Done::Server_Hello_Done(Record_Writer& writer,
- TLS_Handshake_Hash& hash)
- {
- send(writer, hash);
- }
-
-/*
-* Serialize a Server Hello Done message
-*/
-MemoryVector<byte> Server_Hello_Done::serialize() const
- {
- return MemoryVector<byte>();
- }
-
-/*
-* Deserialize a Server Hello Done message
-*/
-void Server_Hello_Done::deserialize(const MemoryRegion<byte>& buf)
- {
- if(buf.size())
- throw Decoding_Error("Server_Hello_Done: Must be empty, and is not");
- }
-
}
diff --git a/src/tls/info.txt b/src/tls/info.txt
index 6654c3b80..9473b0ae2 100644
--- a/src/tls/info.txt
+++ b/src/tls/info.txt
@@ -22,34 +22,35 @@ tls_suites.h
<header:internal>
tls_alerts.h
-tls_handshake_hash.h
tls_extensions.h
+tls_handshake_hash.h
+tls_handshake_state.h
tls_messages.h
tls_reader.h
tls_session_key.h
-tls_handshake_state.h
</header:internal>
<source>
+c_hello.cpp
c_kex.cpp
cert_req.cpp
cert_ver.cpp
finished.cpp
-tls_handshake_hash.cpp
-tls_extensions.cpp
-hello.cpp
+next_protocol.cpp
rec_read.cpp
rec_wri.cpp
+s_hello.cpp
s_kex.cpp
-next_protocol.cpp
tls_channel.cpp
tls_client.cpp
+tls_extensions.cpp
+tls_handshake_hash.cpp
+tls_handshake_state.cpp
tls_policy.cpp
tls_server.cpp
-tls_session_key.cpp
tls_session.cpp
+tls_session_key.cpp
tls_session_manager.cpp
-tls_handshake_state.cpp
tls_suites.cpp
</source>
diff --git a/src/tls/s_hello.cpp b/src/tls/s_hello.cpp
new file mode 100644
index 000000000..5ffb1e7d4
--- /dev/null
+++ b/src/tls/s_hello.cpp
@@ -0,0 +1,201 @@
+;/*
+* TLS Server Hello and Server Hello Done
+* (C) 2004-2011 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#include <botan/internal/tls_messages.h>
+#include <botan/internal/tls_reader.h>
+#include <botan/internal/tls_session_key.h>
+#include <botan/internal/tls_extensions.h>
+#include <botan/tls_record.h>
+#include <botan/internal/stl_util.h>
+
+namespace Botan {
+
+/*
+* Create a new Server Hello message
+*/
+Server_Hello::Server_Hello(Record_Writer& writer,
+ TLS_Handshake_Hash& hash,
+ Version_Code version,
+ const Client_Hello& c_hello,
+ const std::vector<X509_Certificate>& certs,
+ const TLS_Policy& policy,
+ bool client_has_secure_renegotiation,
+ const MemoryRegion<byte>& reneg_info,
+ bool client_has_npn,
+ const std::vector<std::string>& next_protocols,
+ RandomNumberGenerator& rng) :
+ s_version(version),
+ m_session_id(rng.random_vec(32)),
+ s_random(rng.random_vec(32)),
+ m_fragment_size(c_hello.fragment_size()),
+ m_secure_renegotiation(client_has_secure_renegotiation),
+ m_renegotiation_info(reneg_info),
+ m_next_protocol(client_has_npn),
+ m_next_protocols(next_protocols)
+ {
+ bool have_rsa = false, have_dsa = false;
+
+ for(size_t i = 0; i != certs.size(); ++i)
+ {
+ Public_Key* key = certs[i].subject_public_key();
+ if(key->algo_name() == "RSA")
+ have_rsa = true;
+
+ if(key->algo_name() == "DSA")
+ have_dsa = true;
+ }
+
+ suite = policy.choose_suite(c_hello.ciphersuites(), have_rsa, have_dsa, false);
+
+ if(suite == 0)
+ throw TLS_Exception(HANDSHAKE_FAILURE,
+ "Can't agree on a ciphersuite with client");
+
+ comp_method = policy.choose_compression(c_hello.compression_methods());
+
+ send(writer, hash);
+ }
+
+/*
+* Create a new Server Hello message
+*/
+Server_Hello::Server_Hello(Record_Writer& writer,
+ TLS_Handshake_Hash& hash,
+ const MemoryRegion<byte>& session_id,
+ Version_Code ver,
+ u16bit ciphersuite,
+ byte compression,
+ size_t max_fragment_size,
+ bool client_has_secure_renegotiation,
+ const MemoryRegion<byte>& reneg_info,
+ bool client_has_npn,
+ const std::vector<std::string>& next_protocols,
+ RandomNumberGenerator& rng) :
+ s_version(ver),
+ m_session_id(session_id),
+ s_random(rng.random_vec(32)),
+ suite(ciphersuite),
+ comp_method(compression),
+ m_fragment_size(max_fragment_size),
+ m_secure_renegotiation(client_has_secure_renegotiation),
+ m_renegotiation_info(reneg_info),
+ m_next_protocol(client_has_npn),
+ m_next_protocols(next_protocols)
+ {
+ send(writer, hash);
+ }
+
+/*
+* Serialize a Server Hello message
+*/
+MemoryVector<byte> Server_Hello::serialize() const
+ {
+ MemoryVector<byte> buf;
+
+ buf.push_back(static_cast<byte>(s_version >> 8));
+ buf.push_back(static_cast<byte>(s_version ));
+ buf += s_random;
+
+ append_tls_length_value(buf, m_session_id, 1);
+
+ buf.push_back(get_byte(0, suite));
+ buf.push_back(get_byte(1, suite));
+
+ buf.push_back(comp_method);
+
+ TLS_Extensions extensions;
+
+ if(m_secure_renegotiation)
+ extensions.push_back(new Renegotation_Extension(m_renegotiation_info));
+
+ if(m_fragment_size != 0)
+ extensions.push_back(new Maximum_Fragment_Length(m_fragment_size));
+
+ if(m_next_protocol)
+ extensions.push_back(new Next_Protocol_Negotiation(m_next_protocols));
+
+ buf += extensions.serialize();
+
+ return buf;
+ }
+
+/*
+* Deserialize a Server Hello message
+*/
+void Server_Hello::deserialize(const MemoryRegion<byte>& buf)
+ {
+ m_secure_renegotiation = false;
+ m_next_protocol = false;
+
+ if(buf.size() < 38)
+ throw Decoding_Error("Server_Hello: Packet corrupted");
+
+ TLS_Data_Reader reader(buf);
+
+ s_version = static_cast<Version_Code>(reader.get_u16bit());
+
+ if(s_version != SSL_V3 && s_version != TLS_V10 && s_version != TLS_V11)
+ {
+ throw TLS_Exception(PROTOCOL_VERSION,
+ "Server_Hello: Unsupported server version");
+ }
+
+ s_random = reader.get_fixed<byte>(32);
+
+ m_session_id = reader.get_range<byte>(1, 0, 32);
+
+ suite = reader.get_u16bit();
+
+ comp_method = reader.get_byte();
+
+ TLS_Extensions extensions(reader);
+
+ for(size_t i = 0; i != extensions.count(); ++i)
+ {
+ TLS_Extension* extn = extensions.at(i);
+
+ if(Renegotation_Extension* reneg = dynamic_cast<Renegotation_Extension*>(extn))
+ {
+ // checked by TLS_Client / TLS_Server as they know the handshake state
+ m_secure_renegotiation = true;
+ m_renegotiation_info = reneg->renegotiation_info();
+ }
+ else if(Next_Protocol_Negotiation* npn = dynamic_cast<Next_Protocol_Negotiation*>(extn))
+ {
+ m_next_protocols = npn->protocols();
+ m_next_protocol = true;
+ }
+ }
+ }
+
+/*
+* Create a new Server Hello Done message
+*/
+Server_Hello_Done::Server_Hello_Done(Record_Writer& writer,
+ TLS_Handshake_Hash& hash)
+ {
+ send(writer, hash);
+ }
+
+/*
+* Serialize a Server Hello Done message
+*/
+MemoryVector<byte> Server_Hello_Done::serialize() const
+ {
+ return MemoryVector<byte>();
+ }
+
+/*
+* Deserialize a Server Hello Done message
+*/
+void Server_Hello_Done::deserialize(const MemoryRegion<byte>& buf)
+ {
+ if(buf.size())
+ throw Decoding_Error("Server_Hello_Done: Must be empty, and is not");
+ }
+
+}
diff --git a/src/tls/tls_extensions.cpp b/src/tls/tls_extensions.cpp
index a6ab13f46..c74790ea1 100644
--- a/src/tls/tls_extensions.cpp
+++ b/src/tls/tls_extensions.cpp
@@ -9,8 +9,6 @@
#include <botan/internal/tls_reader.h>
#include <botan/tls_exceptn.h>
-#include <stdio.h>
-
namespace Botan {
namespace {
@@ -244,8 +242,6 @@ Next_Protocol_Negotiation::Next_Protocol_Negotiation(TLS_Data_Reader& reader,
{
const std::string p = reader.get_string(1, 0, 255);
- printf("Protocol option %s\n", p.c_str());
-
if(bytes_remaining < p.size() + 1)
throw Decoding_Error("Bad encoding for next protocol extension");
diff --git a/src/tls/tls_messages.h b/src/tls/tls_messages.h
index 9c61501c9..67647d5a3 100644
--- a/src/tls/tls_messages.h
+++ b/src/tls/tls_messages.h
@@ -154,24 +154,28 @@ class Server_Hello : public Handshake_Message
Server_Hello(Record_Writer& writer,
TLS_Handshake_Hash& hash,
+ Version_Code version,
+ const Client_Hello& other,
+ const std::vector<X509_Certificate>& certs,
const TLS_Policy& policies,
- RandomNumberGenerator& rng,
bool client_has_secure_renegotiation,
const MemoryRegion<byte>& reneg_info,
- const std::vector<X509_Certificate>& certs,
- const Client_Hello& other,
- Version_Code version);
+ bool client_has_npn,
+ const std::vector<std::string>& next_protocols,
+ RandomNumberGenerator& rng);
Server_Hello(Record_Writer& writer,
TLS_Handshake_Hash& hash,
- RandomNumberGenerator& rng,
- bool client_has_secure_renegotiation,
- const MemoryRegion<byte>& reneg_info,
const MemoryRegion<byte>& session_id,
- size_t max_fragment_size,
+ Version_Code ver,
u16bit ciphersuite,
byte compression,
- Version_Code ver);
+ size_t max_fragment_size,
+ bool client_has_secure_renegotiation,
+ const MemoryRegion<byte>& reneg_info,
+ bool client_has_npn,
+ const std::vector<std::string>& next_protocols,
+ RandomNumberGenerator& rng);
Server_Hello(const MemoryRegion<byte>& buf) { deserialize(buf); }
private:
diff --git a/src/tls/tls_server.cpp b/src/tls/tls_server.cpp
index 109835e4a..729c185df 100644
--- a/src/tls/tls_server.cpp
+++ b/src/tls/tls_server.cpp
@@ -12,8 +12,6 @@
#include <botan/rsa.h>
#include <botan/dh.h>
-#include <stdio.h>
-
namespace Botan {
namespace {
@@ -87,12 +85,14 @@ TLS_Server::TLS_Server(std::tr1::function<void (const byte[], size_t)> output_fn
TLS_Session_Manager& session_manager,
Credentials_Manager& creds,
const TLS_Policy& policy,
- RandomNumberGenerator& rng) :
+ RandomNumberGenerator& rng,
+ const std::vector<std::string>& next_protocols) :
TLS_Channel(output_fn, proc_fn, handshake_fn),
policy(policy),
rng(rng),
session_manager(session_manager),
- creds(creds)
+ creds(creds),
+ m_possible_protocols(next_protocols)
{
}
@@ -154,7 +154,7 @@ void TLS_Server::process_handshake_msg(Handshake_Type type,
{
state->client_hello = new Client_Hello(contents, type);
- client_requested_hostname = state->client_hello->sni_hostname();
+ m_hostname = state->client_hello->sni_hostname();
state->version = choose_version(state->client_hello->version(),
policy.min_version());
@@ -176,14 +176,16 @@ void TLS_Server::process_handshake_msg(Handshake_Type type,
state->server_hello = new Server_Hello(
writer,
state->hash,
- rng,
- secure_renegotiation.supported(),
- secure_renegotiation.for_server_hello(),
session_info.session_id(),
+ Version_Code(session_info.version()),
session_info.ciphersuite(),
session_info.compression_method(),
session_info.fragment_size(),
- Version_Code(session_info.version()));
+ secure_renegotiation.supported(),
+ secure_renegotiation.for_server_hello(),
+ state->client_hello->next_protocol_negotiation(),
+ m_possible_protocols,
+ rng);
if(session_info.fragment_size())
writer.set_maximum_fragment_size(session_info.fragment_size());
@@ -214,24 +216,26 @@ void TLS_Server::process_handshake_msg(Handshake_Type type,
std::vector<X509_Certificate> server_certs =
creds.cert_chain("",
"tls-server",
- client_requested_hostname);
+ m_hostname);
Private_Key* private_key =
server_certs.empty() ? 0 :
(creds.private_key_for(server_certs[0],
"tls-server",
- client_requested_hostname));
+ m_hostname));
state->server_hello = new Server_Hello(
writer,
state->hash,
+ state->version,
+ *(state->client_hello),
+ server_certs,
policy,
- rng,
secure_renegotiation.supported(),
secure_renegotiation.for_server_hello(),
- server_certs,
- *(state->client_hello),
- state->version);
+ state->client_hello->next_protocol_negotiation(),
+ m_possible_protocols,
+ rng);
if(state->client_hello->fragment_size())
writer.set_maximum_fragment_size(state->client_hello->fragment_size());
@@ -347,10 +351,21 @@ void TLS_Server::process_handshake_msg(Handshake_Type type,
}
else if(type == HANDSHAKE_CCS)
{
- state->set_expected_next(FINISHED);
+ if(state->server_hello->next_protocol_negotiation())
+ state->set_expected_next(NEXT_PROTOCOL);
+ else
+ state->set_expected_next(FINISHED);
reader.activate(state->suite, state->keys, SERVER);
}
+ else if(type == NEXT_PROTOCOL)
+ {
+ state->set_expected_next(FINISHED);
+
+ state->next_protocol = new Next_Protocol(contents);
+
+ m_next_protocol = state->next_protocol->protocol();
+ }
else if(type == FINISHED)
{
state->set_expected_next(HANDSHAKE_NONE);
@@ -389,7 +404,7 @@ void TLS_Server::process_handshake_msg(Handshake_Type type,
secure_renegotiation.supported(),
state->server_hello->fragment_size(),
peer_certs,
- client_requested_hostname,
+ m_hostname,
""
);
diff --git a/src/tls/tls_server.h b/src/tls/tls_server.h
index b08d3f7e8..31e0e9ca4 100644
--- a/src/tls/tls_server.h
+++ b/src/tls/tls_server.h
@@ -30,15 +30,24 @@ class BOTAN_DLL TLS_Server : public TLS_Channel
TLS_Session_Manager& session_manager,
Credentials_Manager& creds,
const TLS_Policy& policy,
- RandomNumberGenerator& rng);
+ RandomNumberGenerator& rng,
+ const std::vector<std::string>& protocols =
+ std::vector<std::string>());
void renegotiate();
/**
- * Return the server name indicator, if set by the client
+ * Return the server name indicator, if sent by the client
*/
std::string server_name_indicator() const
- { return client_requested_hostname; }
+ { return m_hostname; }
+
+ /**
+ * Return the protocol negotiated with NPN extension
+ */
+ std::string next_protocol() const
+ { return m_next_protocol; }
+
private:
void read_handshake(byte, const MemoryRegion<byte>&);
@@ -49,7 +58,9 @@ class BOTAN_DLL TLS_Server : public TLS_Channel
TLS_Session_Manager& session_manager;
Credentials_Manager& creds;
- std::string client_requested_hostname;
+ std::vector<std::string> m_possible_protocols;
+ std::string m_hostname;
+ std::string m_next_protocol;
};
}
diff --git a/src/tls/tls_session_manager.cpp b/src/tls/tls_session_manager.cpp
index 4a0126fc0..e5ec75c88 100644
--- a/src/tls/tls_session_manager.cpp
+++ b/src/tls/tls_session_manager.cpp
@@ -9,8 +9,6 @@
#include <botan/hex.h>
#include <botan/time.h>
-#include <stdio.h>
-
namespace Botan {
bool TLS_Session_Manager_In_Memory::load_from_session_str(