diff options
author | lloyd <[email protected]> | 2011-12-30 18:51:01 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2011-12-30 18:51:01 +0000 |
commit | 766f5eeb5c99936e7ddcf3e4c82095f087b6e928 (patch) | |
tree | 17b95459926b1064b538889a1b7c732ff2298470 /src | |
parent | 07b11b4b3d9c7ef289050252c29bc8174d102148 (diff) |
Add support for the maximum fragment length extension. No hooks for it
on the client side at the moment. Tested with gnutls-cli --recordsize.
Save the fragment size and the secure renegotiation flags in the
session state.
Diffstat (limited to 'src')
-rw-r--r-- | src/tls/hello.cpp | 30 | ||||
-rw-r--r-- | src/tls/rec_wri.cpp | 139 | ||||
-rw-r--r-- | src/tls/tls_extensions.cpp | 59 | ||||
-rw-r--r-- | src/tls/tls_extensions.h | 32 | ||||
-rw-r--r-- | src/tls/tls_messages.h | 7 | ||||
-rw-r--r-- | src/tls/tls_record.h | 19 | ||||
-rw-r--r-- | src/tls/tls_server.cpp | 9 | ||||
-rw-r--r-- | src/tls/tls_session_state.cpp | 68 | ||||
-rw-r--r-- | src/tls/tls_session_state.h | 66 |
9 files changed, 288 insertions, 141 deletions
diff --git a/src/tls/hello.cpp b/src/tls/hello.cpp index 5390b6071..fc19f6802 100644 --- a/src/tls/hello.cpp +++ b/src/tls/hello.cpp @@ -78,6 +78,7 @@ Client_Hello::Client_Hello(Record_Writer& writer, comp_methods(policy.compression()), requested_hostname(hostname), requested_srp_id(srp_identifier), + m_fragment_size(0), has_secure_renegotiation(true), renegotiation_info_bits(reneg_info) { @@ -162,6 +163,8 @@ void Client_Hello::deserialize_sslv2(const MemoryRegion<byte>& buf) has_secure_renegotiation = value_exists(suites, static_cast<u16bit>(TLS_EMPTY_RENEGOTIATION_INFO_SCSV)); + + m_fragment_size = 0; } /* @@ -169,8 +172,6 @@ void Client_Hello::deserialize_sslv2(const MemoryRegion<byte>& buf) */ void Client_Hello::deserialize(const MemoryRegion<byte>& buf) { - has_secure_renegotiation = false; - if(buf.size() == 0) throw Decoding_Error("Client_Hello: Packet corrupted"); @@ -188,6 +189,9 @@ void Client_Hello::deserialize(const MemoryRegion<byte>& buf) comp_methods = reader.get_range_vector<byte>(1, 1, 255); + has_secure_renegotiation = false; + m_fragment_size = 0; + TLS_Extensions extensions(reader); for(size_t i = 0; i != extensions.count(); ++i) @@ -195,9 +199,17 @@ void Client_Hello::deserialize(const MemoryRegion<byte>& buf) TLS_Extension* extn = extensions.at(i); if(Server_Name_Indicator* sni = dynamic_cast<Server_Name_Indicator*>(extn)) + { requested_hostname = sni->host_name(); + } else if(SRP_Identifier* srp = dynamic_cast<SRP_Identifier*>(extn)) + { requested_srp_id = srp->identifier(); + } + else if(Maximum_Fragment_Length* frag = dynamic_cast<Maximum_Fragment_Length*>(extn)) + { + m_fragment_size = frag->fragment_size(); + } else if(Renegotation_Extension* reneg = dynamic_cast<Renegotation_Extension*>(extn)) { // checked by TLS_Client / TLS_Server as they know the handshake state @@ -254,6 +266,7 @@ Server_Hello::Server_Hello(Record_Writer& writer, s_version(ver), sess_id(session_id), 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) { @@ -289,6 +302,7 @@ Server_Hello::Server_Hello(Record_Writer& writer, 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) : @@ -297,6 +311,7 @@ Server_Hello::Server_Hello(Record_Writer& writer, 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) { @@ -321,12 +336,15 @@ MemoryVector<byte> Server_Hello::serialize() const buf.push_back(comp_method); + TLS_Extensions extensions; + if(has_secure_renegotiation) - { - TLS_Extensions extensions; extensions.push_back(new Renegotation_Extension(renegotiation_info_bits)); - buf += extensions.serialize(); - } + + if(m_fragment_size != 0) + extensions.push_back(new Maximum_Fragment_Length(m_fragment_size)); + + buf += extensions.serialize(); return buf; } diff --git a/src/tls/rec_wri.cpp b/src/tls/rec_wri.cpp index a0c332c58..a9a5b4549 100644 --- a/src/tls/rec_wri.cpp +++ b/src/tls/rec_wri.cpp @@ -14,36 +14,47 @@ #include <botan/loadstor.h> #include <botan/libstate.h> +#include <stdio.h> + namespace Botan { /* * Record_Writer Constructor */ -Record_Writer::Record_Writer(std::tr1::function<void (const byte[], size_t)> out, - size_t max_fragment) : - output_fn(out), - max_fragment(clamp(max_fragment, 128, MAX_PLAINTEXT_SIZE)) +Record_Writer::Record_Writer(std::tr1::function<void (const byte[], size_t)> out) : + m_output_fn(out), m_max_fragment(MAX_PLAINTEXT_SIZE) { - mac = 0; + m_mac = 0; reset(); } +void Record_Writer::set_maximum_fragment_size(size_t max_fragment) + { + if(max_fragment == 0) + m_max_fragment = MAX_PLAINTEXT_SIZE; + else + m_max_fragment = clamp(max_fragment, 128, MAX_PLAINTEXT_SIZE); + + printf("Setting max fragment size to %d\n", m_max_fragment); + } + /* * Reset the state */ void Record_Writer::reset() { - cipher.reset(); + m_cipher.reset(); - delete mac; - mac = 0; + delete m_mac; + m_mac = 0; - major = minor = 0; - block_size = 0; - mac_size = 0; - iv_size = 0; + m_major = 0; + m_minor = 0; + m_block_size = 0; + m_mac_size = 0; + m_iv_size = 0; - seq_no = 0; + m_seq_no = 0; } /* @@ -54,8 +65,8 @@ void Record_Writer::set_version(Version_Code version) if(version != SSL_V3 && version != TLS_V10 && version != TLS_V11) throw Invalid_Argument("Record_Writer: Invalid protocol version"); - major = (version >> 8) & 0xFF; - minor = (version & 0xFF); + m_major = (version >> 8) & 0xFF; + m_minor = (version & 0xFF); } /* @@ -65,9 +76,9 @@ void Record_Writer::set_keys(const CipherSuite& suite, const SessionKeys& keys, Connection_Side side) { - cipher.reset(); - delete mac; - mac = 0; + m_cipher.reset(); + delete m_mac; + m_mac = 0; /* RFC 4346: @@ -75,7 +86,7 @@ void Record_Writer::set_keys(const CipherSuite& suite, the first record transmitted under a particular connection state MUST use sequence number 0 */ - seq_no = 0; + m_seq_no = 0; SymmetricKey mac_key, cipher_key; InitializationVector iv; @@ -98,22 +109,22 @@ void Record_Writer::set_keys(const CipherSuite& suite, if(have_block_cipher(cipher_algo)) { - cipher.append(get_cipher( + m_cipher.append(get_cipher( cipher_algo + "/CBC/NoPadding", cipher_key, iv, ENCRYPTION) ); - block_size = block_size_of(cipher_algo); + m_block_size = block_size_of(cipher_algo); - if(major > 3 || (major == 3 && minor >= 2)) - iv_size = block_size; + if(m_major > 3 || (m_major == 3 && m_minor >= 2)) + m_iv_size = m_block_size; else - iv_size = 0; + m_iv_size = 0; } else if(have_stream_cipher(cipher_algo)) { - cipher.append(get_cipher(cipher_algo, cipher_key, ENCRYPTION)); - block_size = 0; - iv_size = 0; + m_cipher.append(get_cipher(cipher_algo, cipher_key, ENCRYPTION)); + m_block_size = 0; + m_iv_size = 0; } else throw Invalid_Argument("Record_Writer: Unknown cipher " + cipher_algo); @@ -122,13 +133,13 @@ void Record_Writer::set_keys(const CipherSuite& suite, { Algorithm_Factory& af = global_state().algorithm_factory(); - if(major == 3 && minor == 0) - mac = af.make_mac("SSL3-MAC(" + mac_algo + ")"); + if(m_major == 3 && m_minor == 0) + m_mac = af.make_mac("SSL3-MAC(" + mac_algo + ")"); else - mac = af.make_mac("HMAC(" + mac_algo + ")"); + m_mac = af.make_mac("HMAC(" + mac_algo + ")"); - mac->set_key(mac_key); - mac_size = mac->output_length(); + m_mac->set_key(mac_key); + m_mac_size = m_mac->output_length(); } else throw Invalid_Argument("Record_Writer: Unknown hash " + mac_algo); @@ -153,7 +164,7 @@ void Record_Writer::send(byte type, const byte input[], size_t length) * * See http://www.openssl.org/~bodo/tls-cbc.txt for background. */ - if((type == APPLICATION) && (block_size > 0) && (iv_size == 0)) + if((type == APPLICATION) && (m_block_size > 0) && (m_iv_size == 0)) { send_record(type, &input[0], 1); input += 1; @@ -162,7 +173,7 @@ void Record_Writer::send(byte type, const byte input[], size_t length) while(length) { - const size_t sending = std::min(length, max_fragment); + const size_t sending = std::min(length, m_max_fragment); send_record(type, &input[0], sending); input += sending; @@ -179,38 +190,38 @@ void Record_Writer::send_record(byte type, const byte input[], size_t length) throw TLS_Exception(INTERNAL_ERROR, "Record_Writer: Compressed packet is too big"); - if(mac_size == 0) + if(m_mac_size == 0) { const byte header[5] = { type, - major, - minor, + m_major, + m_minor, get_byte<u16bit>(0, length), get_byte<u16bit>(1, length) }; - output_fn(header, 5); - output_fn(input, length); + m_output_fn(header, 5); + m_output_fn(input, length); } else { - mac->update_be(seq_no); - mac->update(type); + m_mac->update_be(m_seq_no); + m_mac->update(type); - if(major > 3 || (major == 3 && minor != 0)) + if(m_major > 3 || (m_major == 3 && m_minor != 0)) { - mac->update(major); - mac->update(minor); + m_mac->update(m_major); + m_mac->update(m_minor); } - mac->update(get_byte<u16bit>(0, length)); - mac->update(get_byte<u16bit>(1, length)); - mac->update(input, length); + m_mac->update(get_byte<u16bit>(0, length)); + m_mac->update(get_byte<u16bit>(1, length)); + m_mac->update(input, length); - const size_t buf_size = round_up(iv_size + length + - mac->output_length() + - (block_size ? 1 : 0), - block_size); + const size_t buf_size = round_up(m_iv_size + length + + m_mac->output_length() + + (m_block_size ? 1 : 0), + m_block_size); if(buf_size >= MAX_CIPHERTEXT_SIZE) throw TLS_Exception(INTERNAL_ERROR, @@ -220,30 +231,30 @@ void Record_Writer::send_record(byte type, const byte input[], size_t length) // TLS record header buf[0] = type; - buf[1] = major; - buf[2] = minor; + buf[1] = m_major; + buf[2] = m_minor; buf[3] = get_byte<u16bit>(0, buf_size); buf[4] = get_byte<u16bit>(1, buf_size); byte* buf_write_ptr = &buf[5]; - if(iv_size) + if(m_iv_size) { RandomNumberGenerator& rng = global_state().global_rng(); - rng.randomize(buf_write_ptr, iv_size); - buf_write_ptr += iv_size; + rng.randomize(buf_write_ptr, m_iv_size); + buf_write_ptr += m_iv_size; } copy_mem(buf_write_ptr, input, length); buf_write_ptr += length; - mac->final(buf_write_ptr); - buf_write_ptr += mac->output_length(); + m_mac->final(buf_write_ptr); + buf_write_ptr += m_mac->output_length(); - if(block_size) + if(m_block_size) { const size_t pad_val = - buf_size - (iv_size + length + mac->output_length() + 1); + buf_size - (m_iv_size + length + m_mac->output_length() + 1); for(size_t i = 0; i != pad_val + 1; ++i) { @@ -253,13 +264,13 @@ void Record_Writer::send_record(byte type, const byte input[], size_t length) } // FIXME: this could be done in-place without copying - cipher.process_msg(&buf[5], buf.size() - 5); - size_t got_back = cipher.read(&buf[5], buf.size() - 5, Pipe::LAST_MESSAGE); + m_cipher.process_msg(&buf[5], buf.size() - 5); + size_t got_back = m_cipher.read(&buf[5], buf.size() - 5, Pipe::LAST_MESSAGE); BOTAN_ASSERT_EQUAL(got_back, buf.size()-5, "CBC didn't encrypt full blocks"); - output_fn(&buf[0], buf.size()); + m_output_fn(&buf[0], buf.size()); - seq_no++; + m_seq_no++; } } diff --git a/src/tls/tls_extensions.cpp b/src/tls/tls_extensions.cpp index 1b3858a5a..b793971c5 100644 --- a/src/tls/tls_extensions.cpp +++ b/src/tls/tls_extensions.cpp @@ -13,15 +13,17 @@ namespace Botan { namespace { TLS_Extension* make_extension(TLS_Data_Reader& reader, - u16bit extension_code, - u16bit extension_size) + u16bit code, + u16bit size) { - if(extension_code == TLSEXT_SERVER_NAME_INDICATION) - return new Server_Name_Indicator(reader, extension_size); - else if(extension_code == TLSEXT_SRP_IDENTIFIER) - return new SRP_Identifier(reader, extension_size); - else if(extension_code == TLSEXT_SAFE_RENEGOTIATION) - return new Renegotation_Extension(reader, extension_size); + if(code == TLSEXT_SERVER_NAME_INDICATION) + return new Server_Name_Indicator(reader, size); + else if(code == TLSEXT_MAX_FRAGMENT_LENGTH) + return new Maximum_Fragment_Length(reader, size); + else if(code == TLSEXT_SRP_IDENTIFIER) + return new SRP_Identifier(reader, size); + else if(code == TLSEXT_SAFE_RENEGOTIATION) + return new Renegotation_Extension(reader, size); else return 0; // not known } @@ -184,4 +186,45 @@ MemoryVector<byte> Renegotation_Extension::serialize() const return buf; } +size_t Maximum_Fragment_Length::fragment_size() const + { + switch(val) + { + case 1: + return 512; + case 2: + return 1024; + case 3: + return 2048; + case 4: + return 4096; + default: + throw TLS_Exception(ILLEGAL_PARAMETER, + "Bad value in maximum fragment extension"); + } + } + +Maximum_Fragment_Length::Maximum_Fragment_Length(size_t max_fragment) + { + if(max_fragment == 512) + val = 1; + else if(max_fragment == 1024) + val = 2; + else if(max_fragment == 2048) + val = 3; + else if(max_fragment == 4096) + val = 4; + else + throw std::invalid_argument("Bad setting " + to_string(max_fragment) + + " for maximum fragment size"); + } + +Maximum_Fragment_Length::Maximum_Fragment_Length(TLS_Data_Reader& reader, + u16bit extension_size) + { + if(extension_size != 1) + throw Decoding_Error("Bad size for maximum fragment extension"); + val = reader.get_byte(); + } + } diff --git a/src/tls/tls_extensions.h b/src/tls/tls_extensions.h index bbf4aa851..b1b2ca2e0 100644 --- a/src/tls/tls_extensions.h +++ b/src/tls/tls_extensions.h @@ -107,6 +107,38 @@ class Renegotation_Extension : public TLS_Extension }; /** +* Maximum Fragment Length Negotiation Extension (RFC 4366 sec 3.2) +*/ +class Maximum_Fragment_Length : public TLS_Extension + { + public: + TLS_Handshake_Extension_Type type() const + { return TLSEXT_MAX_FRAGMENT_LENGTH; } + + bool empty() const { return val != 0; } + + size_t fragment_size() const; + + MemoryVector<byte> serialize() const + { + return MemoryVector<byte>(&val, 1); + } + + /** + * @param max_fragment specifies what maximum fragment size to + * advertise. Currently must be one of 512, 1024, 2048, or + * 4096. + */ + Maximum_Fragment_Length(size_t max_fragment); + + Maximum_Fragment_Length(TLS_Data_Reader& reader, + u16bit extension_size); + + private: + byte val; + }; + +/** * Represents a block of extensions in a hello message */ class TLS_Extensions diff --git a/src/tls/tls_messages.h b/src/tls/tls_messages.h index cb56ead6c..8f9195412 100644 --- a/src/tls/tls_messages.h +++ b/src/tls/tls_messages.h @@ -72,6 +72,8 @@ class Client_Hello : public HandshakeMessage bool offered_suite(u16bit ciphersuite) const; + size_t fragment_size() const { return m_fragment_size; } + Client_Hello(Record_Writer& writer, TLS_Handshake_Hash& hash, const TLS_Policy& policy, @@ -101,6 +103,7 @@ class Client_Hello : public HandshakeMessage std::string requested_hostname; std::string requested_srp_id; + size_t m_fragment_size; bool has_secure_renegotiation; MemoryVector<byte> renegotiation_info_bits; }; @@ -126,6 +129,8 @@ class Server_Hello : public HandshakeMessage bool secure_renegotiation() const { return has_secure_renegotiation; } + size_t fragment_size() const { return m_fragment_size; } + const MemoryVector<byte>& renegotiation_info() { return renegotiation_info_bits; } @@ -148,6 +153,7 @@ class Server_Hello : public HandshakeMessage bool client_has_secure_renegotiation, const MemoryRegion<byte>& reneg_info, const MemoryRegion<byte>& session_id, + size_t max_fragment_size, u16bit ciphersuite, byte compression, Version_Code ver); @@ -162,6 +168,7 @@ class Server_Hello : public HandshakeMessage u16bit suite; byte comp_method; + size_t m_fragment_size; bool has_secure_renegotiation; MemoryVector<byte> renegotiation_info_bits; }; diff --git a/src/tls/tls_record.h b/src/tls/tls_record.h index 51a7cd310..55cb66034 100644 --- a/src/tls/tls_record.h +++ b/src/tls/tls_record.h @@ -53,22 +53,23 @@ class BOTAN_DLL Record_Writer void reset(); - Record_Writer(std::tr1::function<void (const byte[], size_t)> output_fn, - size_t max_fragment = MAX_PLAINTEXT_SIZE); + void set_maximum_fragment_size(size_t max_fragment); - ~Record_Writer() { delete mac; } + Record_Writer(std::tr1::function<void (const byte[], size_t)> output_fn); + + ~Record_Writer() { delete m_mac; } private: void send_record(byte type, const byte input[], size_t length); - std::tr1::function<void (const byte[], size_t)> output_fn; + std::tr1::function<void (const byte[], size_t)> m_output_fn; - Pipe cipher; - MessageAuthenticationCode* mac; + Pipe m_cipher; + MessageAuthenticationCode* m_mac; - size_t block_size, mac_size, iv_size, max_fragment; + size_t m_block_size, m_mac_size, m_iv_size, m_max_fragment; - u64bit seq_no; - byte major, minor; + u64bit m_seq_no; + byte m_major, m_minor; }; /** diff --git a/src/tls/tls_server.cpp b/src/tls/tls_server.cpp index 3f65fa735..3077476e3 100644 --- a/src/tls/tls_server.cpp +++ b/src/tls/tls_server.cpp @@ -190,8 +190,12 @@ void TLS_Server::process_handshake_msg(Handshake_Type type, session_info.session_id(), session_info.ciphersuite(), session_info.compression_method(), + session_info.fragment_size(), Version_Code(session_info.version())); + if(session_info.fragment_size()) + writer.set_maximum_fragment_size(session_info.fragment_size()); + state->suite = CipherSuite(state->server_hello->ciphersuite()); state->keys = SessionKeys(state->suite, state->version, @@ -224,6 +228,9 @@ void TLS_Server::process_handshake_msg(Handshake_Type type, rng.random_vec(32), state->version); + if(state->client_hello->fragment_size()) + writer.set_maximum_fragment_size(state->client_hello->fragment_size()); + state->suite = CipherSuite(state->server_hello->ciphersuite()); if(state->suite.sig_type() != TLS_ALGO_SIGNER_ANON) @@ -376,6 +383,8 @@ void TLS_Server::process_handshake_msg(Handshake_Type type, state->server_hello->ciphersuite(), state->server_hello->compression_method(), SERVER, + secure_renegotiation.supported(), + state->server_hello->fragment_size(), peer_certs, client_requested_hostname, "" diff --git a/src/tls/tls_session_state.cpp b/src/tls/tls_session_state.cpp index 9d8d4215d..bac24a5eb 100644 --- a/src/tls/tls_session_state.cpp +++ b/src/tls/tls_session_state.cpp @@ -19,22 +19,26 @@ TLS_Session_Params::TLS_Session_Params(const MemoryRegion<byte>& session_identif u16bit ciphersuite, byte compression_method, Connection_Side side, + bool secure_renegotiation_supported, + size_t fragment_size, const std::vector<X509_Certificate>& certs, const std::string& sni_hostname, const std::string& srp_identifier) : - session_start_time(system_time()), - session_identifier(session_identifier), - session_master_secret(master_secret), - session_version(version), - session_ciphersuite(ciphersuite), - session_compression_method(compression_method), - session_connection_side(side), - session_sni_hostname(sni_hostname), - session_srp_identifier(srp_identifier) + m_start_time(system_time()), + m_identifier(session_identifier), + m_master_secret(master_secret), + m_version(version), + m_ciphersuite(ciphersuite), + m_compression_method(compression_method), + m_connection_side(side), + m_secure_renegotiation_supported(secure_renegotiation_supported), + m_fragment_size(fragment_size), + m_sni_hostname(sni_hostname), + m_srp_identifier(srp_identifier) { // FIXME: encode all of them? if(certs.size()) - session_peer_certificate = certs[0].BER_encode(); + m_peer_certificate = certs[0].BER_encode(); } TLS_Session_Params::TLS_Session_Params(const byte ber[], size_t ber_len) @@ -48,20 +52,22 @@ TLS_Session_Params::TLS_Session_Params(const byte ber[], size_t ber_len) BER_Decoder(ber, ber_len) .decode_and_check(static_cast<size_t>(TLS_SESSION_PARAM_STRUCT_VERSION), "Unknown version in session structure") - .decode(session_identifier, OCTET_STRING) - .decode_integer_type(session_start_time) - .decode_integer_type(session_version) - .decode_integer_type(session_ciphersuite) - .decode_integer_type(session_compression_method) + .decode(m_identifier, OCTET_STRING) + .decode_integer_type(m_start_time) + .decode_integer_type(m_version) + .decode_integer_type(m_ciphersuite) + .decode_integer_type(m_compression_method) .decode_integer_type(side_code) - .decode(session_master_secret, OCTET_STRING) - .decode(session_peer_certificate, OCTET_STRING) + .decode_integer_type(m_fragment_size) + .decode(m_secure_renegotiation_supported) + .decode(m_master_secret, OCTET_STRING) + .decode(m_peer_certificate, OCTET_STRING) .decode(sni_hostname_str) .decode(srp_identifier_str); - session_sni_hostname = sni_hostname_str.value(); - session_srp_identifier = srp_identifier_str.value(); - session_connection_side = static_cast<Connection_Side>(side_code); + m_sni_hostname = sni_hostname_str.value(); + m_srp_identifier = srp_identifier_str.value(); + m_connection_side = static_cast<Connection_Side>(side_code); } SecureVector<byte> TLS_Session_Params::BER_encode() const @@ -69,16 +75,18 @@ SecureVector<byte> TLS_Session_Params::BER_encode() const return DER_Encoder() .start_cons(SEQUENCE) .encode(static_cast<size_t>(TLS_SESSION_PARAM_STRUCT_VERSION)) - .encode(session_identifier, OCTET_STRING) - .encode(static_cast<size_t>(session_start_time)) - .encode(static_cast<size_t>(session_version)) - .encode(static_cast<size_t>(session_ciphersuite)) - .encode(static_cast<size_t>(session_compression_method)) - .encode(static_cast<size_t>(session_connection_side)) - .encode(session_master_secret, OCTET_STRING) - .encode(session_peer_certificate, OCTET_STRING) - .encode(ASN1_String(session_sni_hostname, UTF8_STRING)) - .encode(ASN1_String(session_srp_identifier, UTF8_STRING)) + .encode(m_identifier, OCTET_STRING) + .encode(static_cast<size_t>(m_start_time)) + .encode(static_cast<size_t>(m_version)) + .encode(static_cast<size_t>(m_ciphersuite)) + .encode(static_cast<size_t>(m_compression_method)) + .encode(static_cast<size_t>(m_connection_side)) + .encode(static_cast<size_t>(m_fragment_size)) + .encode(m_secure_renegotiation_supported) + .encode(m_master_secret, OCTET_STRING) + .encode(m_peer_certificate, OCTET_STRING) + .encode(ASN1_String(m_sni_hostname, UTF8_STRING)) + .encode(ASN1_String(m_srp_identifier, UTF8_STRING)) .end_cons() .get_contents(); } diff --git a/src/tls/tls_session_state.h b/src/tls/tls_session_state.h index 3f1b52a00..eefdc4b67 100644 --- a/src/tls/tls_session_state.h +++ b/src/tls/tls_session_state.h @@ -28,11 +28,13 @@ class BOTAN_DLL TLS_Session_Params * Uninitialized session */ TLS_Session_Params() : - session_start_time(0), - session_version(0), - session_ciphersuite(0), - session_compression_method(0), - session_connection_side(static_cast<Connection_Side>(0)) + m_start_time(0), + m_version(0), + m_ciphersuite(0), + m_compression_method(0), + m_connection_side(static_cast<Connection_Side>(0)), + m_secure_renegotiation_supported(false), + m_fragment_size(0) {} /** @@ -44,6 +46,8 @@ class BOTAN_DLL TLS_Session_Params u16bit ciphersuite, byte compression_method, Connection_Side side, + bool secure_renegotiation_supported, + size_t fragment_size, const std::vector<X509_Certificate>& peer_certs, const std::string& sni_hostname = "", const std::string& srp_identifier = ""); @@ -64,67 +68,81 @@ class BOTAN_DLL TLS_Session_Params * Get the version of the saved session */ Version_Code version() const - { return static_cast<Version_Code>(session_version); } + { return static_cast<Version_Code>(m_version); } /** * Get the ciphersuite of the saved session */ - u16bit ciphersuite() const { return session_ciphersuite; } + u16bit ciphersuite() const { return m_ciphersuite; } /** * Get the compression method used in the saved session */ - byte compression_method() const { return session_compression_method; } + byte compression_method() const { return m_compression_method; } /** * Get which side of the connection the resumed session we are/were * acting as. */ - Connection_Side side() const { return session_connection_side; } + Connection_Side side() const { return m_connection_side; } /** * Get the SNI hostname (if sent by the client in the initial handshake) */ - std::string sni_hostname() const { return session_sni_hostname; } + std::string sni_hostname() const { return m_sni_hostname; } /** * Get the SRP identity (if sent by the client in the initial handshake) */ - std::string srp_identifier() const { return session_srp_identifier; } + std::string srp_identifier() const { return m_srp_identifier; } /** * Get the saved master secret */ const SecureVector<byte>& master_secret() const - { return session_master_secret; } + { return m_master_secret; } /** * Get the session identifier */ const MemoryVector<byte>& session_id() const - { return session_identifier; } + { return m_identifier; } + + /** + * Get the negotiated maximum fragment size (or 0 if default) + */ + size_t fragment_size() const { return m_fragment_size; } + + /** + * Is secure negotiation supported? + */ + bool secure_negotiation() const + { return m_secure_renegotiation_supported; } /** * Get the time this session began (seconds since Epoch) */ - u64bit start_time() const { return session_start_time; } + u64bit start_time() const { return m_start_time; } private: enum { TLS_SESSION_PARAM_STRUCT_VERSION = 1 }; - u64bit session_start_time; + u64bit m_start_time; + + MemoryVector<byte> m_identifier; + SecureVector<byte> m_master_secret; - MemoryVector<byte> session_identifier; - SecureVector<byte> session_master_secret; + u16bit m_version; + u16bit m_ciphersuite; + byte m_compression_method; + Connection_Side m_connection_side; - u16bit session_version; - u16bit session_ciphersuite; - byte session_compression_method; - Connection_Side session_connection_side; + bool m_secure_renegotiation_supported; + size_t m_fragment_size; - MemoryVector<byte> session_peer_certificate; // optional - std::string session_sni_hostname; // optional - std::string session_srp_identifier; // optional + MemoryVector<byte> m_peer_certificate; // optional + std::string m_sni_hostname; // optional + std::string m_srp_identifier; // optional }; /** |