Botan  1.11.15
src/lib/tls/msg_client_hello.cpp
Go to the documentation of this file.
00001 /*
00002 * TLS Hello Request and Client Hello Messages
00003 * (C) 2004-2011 Jack Lloyd
00004 *
00005 * Botan is released under the Simplified BSD License (see license.txt)
00006 */
00007 
00008 #include <botan/internal/tls_messages.h>
00009 #include <botan/internal/tls_reader.h>
00010 #include <botan/internal/tls_session_key.h>
00011 #include <botan/internal/tls_handshake_io.h>
00012 #include <botan/internal/stl_util.h>
00013 #include <chrono>
00014 
00015 namespace Botan {
00016 
00017 namespace TLS {
00018 
00019 enum {
00020    TLS_EMPTY_RENEGOTIATION_INFO_SCSV        = 0x00FF,
00021    TLS_FALLBACK_SCSV                        = 0x5600
00022 };
00023 
00024 std::vector<byte> make_hello_random(RandomNumberGenerator& rng,
00025                                     const Policy& policy)
00026    {
00027    std::vector<byte> buf(32);
00028    rng.randomize(&buf[0], buf.size());
00029 
00030    if(policy.include_time_in_hello_random())
00031       {
00032       const u32bit time32 = static_cast<u32bit>(
00033          std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()));
00034 
00035       store_be(time32, &buf[0]);
00036       }
00037 
00038    return buf;
00039    }
00040 
00041 /*
00042 * Create a new Hello Request message
00043 */
00044 Hello_Request::Hello_Request(Handshake_IO& io)
00045    {
00046    io.send(*this);
00047    }
00048 
00049 /*
00050 * Deserialize a Hello Request message
00051 */
00052 Hello_Request::Hello_Request(const std::vector<byte>& buf)
00053    {
00054    if(buf.size())
00055       throw Decoding_Error("Bad Hello_Request, has non-zero size");
00056    }
00057 
00058 /*
00059 * Serialize a Hello Request message
00060 */
00061 std::vector<byte> Hello_Request::serialize() const
00062    {
00063    return std::vector<byte>();
00064    }
00065 
00066 /*
00067 * Create a new Client Hello message
00068 */
00069 Client_Hello::Client_Hello(Handshake_IO& io,
00070                            Handshake_Hash& hash,
00071                            Protocol_Version version,
00072                            const Policy& policy,
00073                            RandomNumberGenerator& rng,
00074                            const std::vector<byte>& reneg_info,
00075                            bool next_protocol,
00076                            const std::string& hostname,
00077                            const std::string& srp_identifier) :
00078    m_version(version),
00079    m_random(make_hello_random(rng, policy)),
00080    m_suites(policy.ciphersuite_list(m_version, (srp_identifier != ""))),
00081    m_comp_methods(policy.compression())
00082    {
00083    m_extensions.add(new Renegotiation_Extension(reneg_info));
00084    m_extensions.add(new SRP_Identifier(srp_identifier));
00085    m_extensions.add(new Server_Name_Indicator(hostname));
00086    m_extensions.add(new Session_Ticket());
00087    m_extensions.add(new Supported_Elliptic_Curves(policy.allowed_ecc_curves()));
00088 
00089    if(policy.negotiate_heartbeat_support())
00090       m_extensions.add(new Heartbeat_Support_Indicator(true));
00091 
00092    if(m_version.supports_negotiable_signature_algorithms())
00093       m_extensions.add(new Signature_Algorithms(policy.allowed_signature_hashes(),
00094                                                 policy.allowed_signature_methods()));
00095 
00096    if(m_version.is_datagram_protocol())
00097      m_extensions.add(new SRTP_Protection_Profiles(policy.srtp_profiles()));
00098 
00099    if(reneg_info.empty() && next_protocol)
00100       m_extensions.add(new Next_Protocol_Notification());
00101 
00102    BOTAN_ASSERT(policy.acceptable_protocol_version(version),
00103                 "Our policy accepts the version we are offering");
00104 
00105    if(policy.send_fallback_scsv(version))
00106       m_suites.push_back(TLS_FALLBACK_SCSV);
00107 
00108    hash.update(io.send(*this));
00109    }
00110 
00111 /*
00112 * Create a new Client Hello message (session resumption case)
00113 */
00114 Client_Hello::Client_Hello(Handshake_IO& io,
00115                            Handshake_Hash& hash,
00116                            const Policy& policy,
00117                            RandomNumberGenerator& rng,
00118                            const std::vector<byte>& reneg_info,
00119                            const Session& session,
00120                            bool next_protocol) :
00121    m_version(session.version()),
00122    m_session_id(session.session_id()),
00123    m_random(make_hello_random(rng, policy)),
00124    m_suites(policy.ciphersuite_list(m_version, (session.srp_identifier() != ""))),
00125    m_comp_methods(policy.compression())
00126    {
00127    if(!value_exists(m_suites, session.ciphersuite_code()))
00128       m_suites.push_back(session.ciphersuite_code());
00129 
00130    if(!value_exists(m_comp_methods, session.compression_method()))
00131       m_comp_methods.push_back(session.compression_method());
00132 
00133    m_extensions.add(new Renegotiation_Extension(reneg_info));
00134    m_extensions.add(new SRP_Identifier(session.srp_identifier()));
00135    m_extensions.add(new Server_Name_Indicator(session.server_info().hostname()));
00136    m_extensions.add(new Session_Ticket(session.session_ticket()));
00137    m_extensions.add(new Supported_Elliptic_Curves(policy.allowed_ecc_curves()));
00138 
00139    if(policy.negotiate_heartbeat_support())
00140       m_extensions.add(new Heartbeat_Support_Indicator(true));
00141 
00142    if(session.fragment_size() != 0)
00143       m_extensions.add(new Maximum_Fragment_Length(session.fragment_size()));
00144 
00145    if(m_version.supports_negotiable_signature_algorithms())
00146       m_extensions.add(new Signature_Algorithms(policy.allowed_signature_hashes(),
00147                                                 policy.allowed_signature_methods()));
00148 
00149    if(reneg_info.empty() && next_protocol)
00150       m_extensions.add(new Next_Protocol_Notification());
00151 
00152    hash.update(io.send(*this));
00153    }
00154 
00155 void Client_Hello::update_hello_cookie(const Hello_Verify_Request& hello_verify)
00156    {
00157    if(!m_version.is_datagram_protocol())
00158       throw std::runtime_error("Cannot use hello cookie with stream protocol");
00159 
00160    m_hello_cookie = hello_verify.cookie();
00161    }
00162 
00163 /*
00164 * Serialize a Client Hello message
00165 */
00166 std::vector<byte> Client_Hello::serialize() const
00167    {
00168    std::vector<byte> buf;
00169 
00170    buf.push_back(m_version.major_version());
00171    buf.push_back(m_version.minor_version());
00172    buf += m_random;
00173 
00174    append_tls_length_value(buf, m_session_id, 1);
00175 
00176    if(m_version.is_datagram_protocol())
00177       append_tls_length_value(buf, m_hello_cookie, 1);
00178 
00179    append_tls_length_value(buf, m_suites, 2);
00180    append_tls_length_value(buf, m_comp_methods, 1);
00181 
00182    /*
00183    * May not want to send extensions at all in some cases. If so,
00184    * should include SCSV value (if reneg info is empty, if not we are
00185    * renegotiating with a modern server)
00186    */
00187 
00188    buf += m_extensions.serialize();
00189 
00190    return buf;
00191    }
00192 
00193 /*
00194 * Read a counterparty client hello
00195 */
00196 Client_Hello::Client_Hello(const std::vector<byte>& buf)
00197    {
00198    if(buf.size() == 0)
00199       throw Decoding_Error("Client_Hello: Packet corrupted");
00200 
00201    if(buf.size() < 41)
00202       throw Decoding_Error("Client_Hello: Packet corrupted");
00203 
00204    TLS_Data_Reader reader("ClientHello", buf);
00205 
00206    const byte major_version = reader.get_byte();
00207    const byte minor_version = reader.get_byte();
00208 
00209    m_version = Protocol_Version(major_version, minor_version);
00210 
00211    m_random = reader.get_fixed<byte>(32);
00212 
00213    if(m_version.is_datagram_protocol())
00214       m_hello_cookie = reader.get_range<byte>(1, 0, 255);
00215 
00216    m_session_id = reader.get_range<byte>(1, 0, 32);
00217 
00218    m_suites = reader.get_range_vector<u16bit>(2, 1, 32767);
00219 
00220    m_comp_methods = reader.get_range_vector<byte>(1, 1, 255);
00221 
00222    m_extensions.deserialize(reader);
00223 
00224    if(offered_suite(static_cast<u16bit>(TLS_EMPTY_RENEGOTIATION_INFO_SCSV)))
00225       {
00226       if(Renegotiation_Extension* reneg = m_extensions.get<Renegotiation_Extension>())
00227          {
00228          if(!reneg->renegotiation_info().empty())
00229             throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
00230                                 "Client sent renegotiation SCSV and non-empty extension");
00231          }
00232       else
00233          {
00234          // add fake extension
00235          m_extensions.add(new Renegotiation_Extension());
00236          }
00237       }
00238    }
00239 
00240 bool Client_Hello::sent_fallback_scsv() const
00241    {
00242    return offered_suite(static_cast<u16bit>(TLS_FALLBACK_SCSV));
00243    }
00244 
00245 /*
00246 * Check if we offered this ciphersuite
00247 */
00248 bool Client_Hello::offered_suite(u16bit ciphersuite) const
00249    {
00250    for(size_t i = 0; i != m_suites.size(); ++i)
00251       if(m_suites[i] == ciphersuite)
00252          return true;
00253    return false;
00254    }
00255 
00256 }
00257 
00258 }