diff options
Diffstat (limited to 'src/tls/hello.cpp')
-rw-r--r-- | src/tls/hello.cpp | 163 |
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; } } } |