aboutsummaryrefslogtreecommitdiffstats
path: root/src/tls/hello.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/tls/hello.cpp')
-rw-r--r--src/tls/hello.cpp163
1 files changed, 95 insertions, 68 deletions
diff --git a/src/tls/hello.cpp b/src/tls/hello.cpp
index 17a624381..8c13cb8f6 100644
--- a/src/tls/hello.cpp
+++ b/src/tls/hello.cpp
@@ -1,4 +1,4 @@
-/*
+;/*
* TLS Hello Messages
* (C) 2004-2011 Jack Lloyd
*
@@ -70,17 +70,19 @@ Client_Hello::Client_Hello(Record_Writer& writer,
const TLS_Policy& policy,
RandomNumberGenerator& rng,
const MemoryRegion<byte>& reneg_info,
+ bool next_protocol,
const std::string& hostname,
const std::string& srp_identifier) :
- c_version(policy.pref_version()),
- c_random(rng.random_vec(32)),
- suites(policy.ciphersuites(srp_identifier != "")),
- comp_methods(policy.compression()),
- requested_hostname(hostname),
- requested_srp_id(srp_identifier),
+ m_version(policy.pref_version()),
+ m_random(rng.random_vec(32)),
+ m_suites(policy.ciphersuites(srp_identifier != "")),
+ m_comp_methods(policy.compression()),
+ m_hostname(hostname),
+ m_srp_identifier(srp_identifier),
+ m_next_protocol(next_protocol),
m_fragment_size(0),
- has_secure_renegotiation(true),
- renegotiation_info_bits(reneg_info)
+ m_secure_renegotiation(true),
+ m_renegotiation_info(reneg_info)
{
send(writer, hash);
}
@@ -91,17 +93,19 @@ Client_Hello::Client_Hello(Record_Writer& writer,
Client_Hello::Client_Hello(Record_Writer& writer,
TLS_Handshake_Hash& hash,
RandomNumberGenerator& rng,
- const TLS_Session& session) :
- c_version(session.version()),
- sess_id(session.session_id()),
- c_random(rng.random_vec(32)),
- requested_hostname(session.sni_hostname()),
- requested_srp_id(session.srp_identifier()),
+ const TLS_Session& session,
+ bool next_protocol) :
+ m_version(session.version()),
+ m_session_id(session.session_id()),
+ m_random(rng.random_vec(32)),
+ m_hostname(session.sni_hostname()),
+ m_srp_identifier(session.srp_identifier()),
+ m_next_protocol(next_protocol),
m_fragment_size(session.fragment_size()),
- has_secure_renegotiation(session.secure_renegotiation())
+ m_secure_renegotiation(session.secure_renegotiation())
{
- suites.push_back(session.ciphersuite());
- comp_methods.push_back(session.compression_method());
+ m_suites.push_back(session.ciphersuite());
+ m_comp_methods.push_back(session.compression_method());
send(writer, hash);
}
@@ -113,13 +117,13 @@ MemoryVector<byte> Client_Hello::serialize() const
{
MemoryVector<byte> buf;
- buf.push_back(static_cast<byte>(c_version >> 8));
- buf.push_back(static_cast<byte>(c_version ));
- buf += c_random;
+ buf.push_back(static_cast<byte>(m_version >> 8));
+ buf.push_back(static_cast<byte>(m_version ));
+ buf += m_random;
- append_tls_length_value(buf, sess_id, 1);
- append_tls_length_value(buf, suites, 2);
- append_tls_length_value(buf, comp_methods, 1);
+ append_tls_length_value(buf, m_session_id, 1);
+ append_tls_length_value(buf, m_suites, 2);
+ append_tls_length_value(buf, m_comp_methods, 1);
/*
* May not want to send extensions at all in some cases.
@@ -131,16 +135,19 @@ MemoryVector<byte> Client_Hello::serialize() const
TLS_Extensions extensions;
// Initial handshake
- if(renegotiation_info_bits.empty())
+ if(m_renegotiation_info.empty())
{
- extensions.push_back(new Renegotation_Extension(renegotiation_info_bits));
- extensions.push_back(new Server_Name_Indicator(requested_hostname));
- extensions.push_back(new SRP_Identifier(requested_srp_id));
+ extensions.push_back(new Renegotation_Extension(m_renegotiation_info));
+ extensions.push_back(new Server_Name_Indicator(m_hostname));
+ extensions.push_back(new SRP_Identifier(m_srp_identifier));
+
+ if(m_next_protocol)
+ extensions.push_back(new Next_Protocol_Negotiation());
}
else
{
// renegotiation
- extensions.push_back(new Renegotation_Extension(renegotiation_info_bits));
+ extensions.push_back(new Renegotation_Extension(m_renegotiation_info));
}
buf += extensions.serialize();
@@ -154,16 +161,16 @@ void Client_Hello::deserialize_sslv2(const MemoryRegion<byte>& buf)
throw Decoding_Error("Client_Hello: SSLv2 hello corrupted");
const size_t cipher_spec_len = make_u16bit(buf[3], buf[4]);
- const size_t sess_id_len = make_u16bit(buf[5], buf[6]);
+ const size_t m_session_id_len = make_u16bit(buf[5], buf[6]);
const size_t challenge_len = make_u16bit(buf[7], buf[8]);
const size_t expected_size =
- (9 + sess_id_len + cipher_spec_len + challenge_len);
+ (9 + m_session_id_len + cipher_spec_len + challenge_len);
if(buf.size() != expected_size)
throw Decoding_Error("Client_Hello: SSLv2 hello corrupted");
- if(sess_id_len != 0 || cipher_spec_len % 3 != 0 ||
+ if(m_session_id_len != 0 || cipher_spec_len % 3 != 0 ||
(challenge_len < 16 || challenge_len > 32))
{
throw Decoding_Error("Client_Hello: SSLv2 hello corrupted");
@@ -174,18 +181,19 @@ void Client_Hello::deserialize_sslv2(const MemoryRegion<byte>& buf)
if(buf[i] != 0) // a SSLv2 cipherspec; ignore it
continue;
- suites.push_back(make_u16bit(buf[i+1], buf[i+2]));
+ m_suites.push_back(make_u16bit(buf[i+1], buf[i+2]));
}
- c_version = static_cast<Version_Code>(make_u16bit(buf[1], buf[2]));
+ m_version = static_cast<Version_Code>(make_u16bit(buf[1], buf[2]));
- c_random.resize(challenge_len);
- copy_mem(&c_random[0], &buf[9+cipher_spec_len+sess_id_len], challenge_len);
+ m_random.resize(challenge_len);
+ copy_mem(&m_random[0], &buf[9+cipher_spec_len+m_session_id_len], challenge_len);
- has_secure_renegotiation =
- value_exists(suites, static_cast<u16bit>(TLS_EMPTY_RENEGOTIATION_INFO_SCSV));
+ m_secure_renegotiation =
+ value_exists(m_suites, static_cast<u16bit>(TLS_EMPTY_RENEGOTIATION_INFO_SCSV));
m_fragment_size = 0;
+ m_next_protocol = false;
}
/*
@@ -201,16 +209,17 @@ void Client_Hello::deserialize(const MemoryRegion<byte>& buf)
TLS_Data_Reader reader(buf);
- c_version = static_cast<Version_Code>(reader.get_u16bit());
- c_random = reader.get_fixed<byte>(32);
+ m_version = static_cast<Version_Code>(reader.get_u16bit());
+ m_random = reader.get_fixed<byte>(32);
- sess_id = reader.get_range<byte>(1, 0, 32);
+ m_session_id = reader.get_range<byte>(1, 0, 32);
- suites = reader.get_range_vector<u16bit>(2, 1, 32767);
+ m_suites = reader.get_range_vector<u16bit>(2, 1, 32767);
- comp_methods = reader.get_range_vector<byte>(1, 1, 255);
+ m_comp_methods = reader.get_range_vector<byte>(1, 1, 255);
- has_secure_renegotiation = false;
+ m_next_protocol = false;
+ m_secure_renegotiation = false;
m_fragment_size = 0;
TLS_Extensions extensions(reader);
@@ -221,11 +230,18 @@ void Client_Hello::deserialize(const MemoryRegion<byte>& buf)
if(Server_Name_Indicator* sni = dynamic_cast<Server_Name_Indicator*>(extn))
{
- requested_hostname = sni->host_name();
+ m_hostname = sni->host_name();
}
else if(SRP_Identifier* srp = dynamic_cast<SRP_Identifier*>(extn))
{
- requested_srp_id = srp->identifier();
+ m_srp_identifier = srp->identifier();
+ }
+ else if(Next_Protocol_Negotiation* npn = dynamic_cast<Next_Protocol_Negotiation*>(extn))
+ {
+ if(!npn->protocols().empty())
+ throw Decoding_Error("Client sent non-empty NPN extension");
+
+ m_next_protocol = true;
}
else if(Maximum_Fragment_Length* frag = dynamic_cast<Maximum_Fragment_Length*>(extn))
{
@@ -234,29 +250,29 @@ void Client_Hello::deserialize(const MemoryRegion<byte>& buf)
else if(Renegotation_Extension* reneg = dynamic_cast<Renegotation_Extension*>(extn))
{
// checked by TLS_Client / TLS_Server as they know the handshake state
- has_secure_renegotiation = true;
- renegotiation_info_bits = reneg->renegotiation_info();
+ m_secure_renegotiation = true;
+ m_renegotiation_info = reneg->renegotiation_info();
}
}
- if(value_exists(suites, static_cast<u16bit>(TLS_EMPTY_RENEGOTIATION_INFO_SCSV)))
+ if(value_exists(m_suites, static_cast<u16bit>(TLS_EMPTY_RENEGOTIATION_INFO_SCSV)))
{
/*
* Clients are allowed to send both the extension and the SCSV
* though it is not recommended. If it did, require that the
* extension value be empty.
*/
- if(has_secure_renegotiation)
+ if(m_secure_renegotiation)
{
- if(!renegotiation_info_bits.empty())
+ if(!m_renegotiation_info.empty())
{
throw TLS_Exception(HANDSHAKE_FAILURE,
"Client send SCSV and non-empty extension");
}
}
- has_secure_renegotiation = true;
- renegotiation_info_bits.clear();
+ m_secure_renegotiation = true;
+ m_renegotiation_info.clear();
}
}
@@ -265,8 +281,8 @@ void Client_Hello::deserialize(const MemoryRegion<byte>& buf)
*/
bool Client_Hello::offered_suite(u16bit ciphersuite) const
{
- for(size_t i = 0; i != suites.size(); ++i)
- if(suites[i] == ciphersuite)
+ for(size_t i = 0; i != m_suites.size(); ++i)
+ if(m_suites[i] == ciphersuite)
return true;
return false;
}
@@ -284,11 +300,12 @@ Server_Hello::Server_Hello(Record_Writer& writer,
const Client_Hello& c_hello,
Version_Code ver) :
s_version(ver),
- sess_id(rng.random_vec(32)),
+ m_session_id(rng.random_vec(32)),
s_random(rng.random_vec(32)),
m_fragment_size(c_hello.fragment_size()),
- has_secure_renegotiation(client_has_secure_renegotiation),
- renegotiation_info_bits(reneg_info)
+ m_secure_renegotiation(client_has_secure_renegotiation),
+ m_renegotiation_info(reneg_info),
+ m_next_protocol(false)
{
bool have_rsa = false, have_dsa = false;
@@ -327,13 +344,14 @@ Server_Hello::Server_Hello(Record_Writer& writer,
byte compression,
Version_Code ver) :
s_version(ver),
- sess_id(session_id),
+ m_session_id(session_id),
s_random(rng.random_vec(32)),
suite(ciphersuite),
comp_method(compression),
m_fragment_size(fragment_size),
- has_secure_renegotiation(client_has_secure_renegotiation),
- renegotiation_info_bits(reneg_info)
+ m_secure_renegotiation(client_has_secure_renegotiation),
+ m_renegotiation_info(reneg_info),
+ m_next_protocol(false)
{
send(writer, hash);
}
@@ -349,7 +367,7 @@ MemoryVector<byte> Server_Hello::serialize() const
buf.push_back(static_cast<byte>(s_version ));
buf += s_random;
- append_tls_length_value(buf, sess_id, 1);
+ append_tls_length_value(buf, m_session_id, 1);
buf.push_back(get_byte(0, suite));
buf.push_back(get_byte(1, suite));
@@ -358,12 +376,15 @@ MemoryVector<byte> Server_Hello::serialize() const
TLS_Extensions extensions;
- if(has_secure_renegotiation)
- extensions.push_back(new Renegotation_Extension(renegotiation_info_bits));
+ 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;
@@ -374,7 +395,8 @@ MemoryVector<byte> Server_Hello::serialize() const
*/
void Server_Hello::deserialize(const MemoryRegion<byte>& buf)
{
- has_secure_renegotiation = false;
+ m_secure_renegotiation = false;
+ m_next_protocol = false;
if(buf.size() < 38)
throw Decoding_Error("Server_Hello: Packet corrupted");
@@ -391,7 +413,7 @@ void Server_Hello::deserialize(const MemoryRegion<byte>& buf)
s_random = reader.get_fixed<byte>(32);
- sess_id = reader.get_range<byte>(1, 0, 32);
+ m_session_id = reader.get_range<byte>(1, 0, 32);
suite = reader.get_u16bit();
@@ -406,8 +428,13 @@ void Server_Hello::deserialize(const MemoryRegion<byte>& buf)
if(Renegotation_Extension* reneg = dynamic_cast<Renegotation_Extension*>(extn))
{
// checked by TLS_Client / TLS_Server as they know the handshake state
- has_secure_renegotiation = true;
- renegotiation_info_bits = reneg->renegotiation_info();
+ 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;
}
}
}