diff options
-rw-r--r-- | doc/manual/tls.rst | 9 | ||||
-rw-r--r-- | src/lib/tls/msg_client_hello.cpp | 3 | ||||
-rw-r--r-- | src/lib/tls/msg_server_hello.cpp | 98 | ||||
-rw-r--r-- | src/lib/tls/tls_client.cpp | 10 | ||||
-rw-r--r-- | src/lib/tls/tls_extensions.cpp | 93 | ||||
-rw-r--r-- | src/lib/tls/tls_extensions.h | 27 | ||||
-rw-r--r-- | src/lib/tls/tls_messages.h | 48 | ||||
-rw-r--r-- | src/lib/tls/tls_policy.cpp | 25 | ||||
-rw-r--r-- | src/lib/tls/tls_policy.h | 7 | ||||
-rw-r--r-- | src/lib/tls/tls_server.cpp | 71 | ||||
-rw-r--r-- | src/lib/tls/tls_session.cpp | 17 | ||||
-rw-r--r-- | src/lib/tls/tls_session.h | 28 |
12 files changed, 298 insertions, 138 deletions
diff --git a/doc/manual/tls.rst b/doc/manual/tls.rst index ac0f14fe2..0faf9e4d4 100644 --- a/doc/manual/tls.rst +++ b/doc/manual/tls.rst @@ -568,11 +568,12 @@ be negotiated during a handshake. Return a list of ECC curves we are willing to use, in order of preference. - Default: "brainpool512r1", "brainpool384r1", "brainpool256r1", - "secp521r1", "secp384r1", "secp256r1", "secp256k1" + Default: "brainpool512r1", "secp521r1", "brainpool384r1", + "secp384r1", "brainpool256r1", "secp256r1" - Also allowed (disabled by default): "secp224r1", "secp224k1", - "secp192r1", "secp192k1", "secp160r2", "secp160r1", "secp160k1" + Also allowed (disabled by default): "secp256k1", "secp224r1", + "secp224k1", "secp192r1", "secp192k1", "secp160r2", "secp160r1", + "secp160k1" .. cpp:function:: std::vector<byte> compression() const diff --git a/src/lib/tls/msg_client_hello.cpp b/src/lib/tls/msg_client_hello.cpp index 605e094c4..02e28b5c9 100644 --- a/src/lib/tls/msg_client_hello.cpp +++ b/src/lib/tls/msg_client_hello.cpp @@ -93,6 +93,9 @@ Client_Hello::Client_Hello(Handshake_IO& io, m_extensions.add(new Signature_Algorithms(policy.allowed_signature_hashes(), policy.allowed_signature_methods())); + if(m_version.is_datagram_protocol()) + m_extensions.add(new SRTP_Protection_Profiles(policy.srtp_profiles())); + if(reneg_info.empty() && next_protocol) m_extensions.add(new Next_Protocol_Notification()); diff --git a/src/lib/tls/msg_server_hello.cpp b/src/lib/tls/msg_server_hello.cpp index 79c16e53a..8dd7d3595 100644 --- a/src/lib/tls/msg_server_hello.cpp +++ b/src/lib/tls/msg_server_hello.cpp @@ -1,6 +1,6 @@ ;/* * TLS Server Hello and Server Hello Done -* (C) 2004-2011 Jack Lloyd +* (C) 2004-2011,2015 Jack Lloyd * * Released under the terms of the Botan license */ @@ -16,49 +16,103 @@ namespace Botan { namespace TLS { -/* -* Create a new Server Hello message -*/ +// New session case Server_Hello::Server_Hello(Handshake_IO& io, Handshake_Hash& hash, const Policy& policy, - const std::vector<byte>& session_id, - Protocol_Version ver, + RandomNumberGenerator& rng, + const std::vector<byte>& reneg_info, + const Client_Hello& client_hello, + const std::vector<byte>& new_session_id, + Protocol_Version new_session_version, u16bit ciphersuite, byte compression, - size_t max_fragment_size, - bool client_has_secure_renegotiation, - const std::vector<byte>& reneg_info, bool offer_session_ticket, - bool client_has_npn, - const std::vector<std::string>& next_protocols, - bool client_has_heartbeat, - RandomNumberGenerator& rng) : - m_version(ver), - m_session_id(session_id), + const std::vector<std::string>& next_protocols) : + m_version(new_session_version), + m_session_id(new_session_id), m_random(make_hello_random(rng, policy)), m_ciphersuite(ciphersuite), m_comp_method(compression) { - if(client_has_heartbeat && policy.negotiate_heartbeat_support()) - m_extensions.add(new Heartbeat_Support_Indicator(true)); - /* * Even a client that offered SSLv3 and sent the SCSV will get an * extension back. This is probably the right thing to do. */ - if(client_has_secure_renegotiation) + if(client_hello.secure_renegotiation()) m_extensions.add(new Renegotiation_Extension(reneg_info)); - if(max_fragment_size) + if(client_hello.supports_session_ticket() && offer_session_ticket) + m_extensions.add(new Session_Ticket()); + + if(size_t max_fragment_size = client_hello.fragment_size()) m_extensions.add(new Maximum_Fragment_Length(max_fragment_size)); - if(client_has_npn) + if(policy.negotiate_heartbeat_support() && client_hello.supports_heartbeats()) + m_extensions.add(new Heartbeat_Support_Indicator(true)); + + if(client_hello.next_protocol_notification()) m_extensions.add(new Next_Protocol_Notification(next_protocols)); - if(offer_session_ticket) + if(m_version.is_datagram_protocol()) + { + const std::vector<u16bit> server_srtp = policy.srtp_profiles(); + const std::vector<u16bit> client_srtp = client_hello.srtp_profiles(); + + if(!server_srtp.empty() && !client_srtp.empty()) + { + u16bit shared = 0; + // always using server preferences for now + for(auto s : server_srtp) + for(auto c : client_srtp) + { + if(shared == 0 && s == c) + shared = s; + } + + if(shared) + m_extensions.add(new SRTP_Protection_Profiles(shared)); + } + } + + hash.update(io.send(*this)); + } + +// Resuming +Server_Hello::Server_Hello(Handshake_IO& io, + Handshake_Hash& hash, + const Policy& policy, + RandomNumberGenerator& rng, + const std::vector<byte>& reneg_info, + const Client_Hello& client_hello, + Session& resumed_session, + bool offer_session_ticket, + const std::vector<std::string>& next_protocols) : + m_version(resumed_session.version()), + m_session_id(client_hello.session_id()), + m_random(make_hello_random(rng, policy)), + m_ciphersuite(resumed_session.ciphersuite_code()), + m_comp_method(resumed_session.compression_method()) + { + /* + * Even a client that offered SSLv3 and sent the SCSV will get an + * extension back. This is probably the right thing to do. + */ + if(client_hello.secure_renegotiation()) + m_extensions.add(new Renegotiation_Extension(reneg_info)); + + if(client_hello.supports_session_ticket() && offer_session_ticket) m_extensions.add(new Session_Ticket()); + if(size_t max_fragment_size = resumed_session.fragment_size()) + m_extensions.add(new Maximum_Fragment_Length(max_fragment_size)); + + if(policy.negotiate_heartbeat_support() && client_hello.supports_heartbeats()) + m_extensions.add(new Heartbeat_Support_Indicator(true)); + + if(client_hello.next_protocol_notification()) + m_extensions.add(new Next_Protocol_Notification(next_protocols)); + hash.update(io.send(*this)); } diff --git a/src/lib/tls/tls_client.cpp b/src/lib/tls/tls_client.cpp index 7c3e48ca6..1e858a0b0 100644 --- a/src/lib/tls/tls_client.cpp +++ b/src/lib/tls/tls_client.cpp @@ -233,6 +233,13 @@ void Client::process_handshake_msg(const Handshake_State* active_state, " but we did not request it"); } + if(u16bit srtp = state.server_hello()->srtp_profile()) + { + if(!value_exists(state.client_hello()->srtp_profiles(), srtp)) + throw TLS_Exception(Alert::HANDSHAKE_FAILURE, + "Server replied with DTLS-SRTP alg we did not send"); + } + state.set_version(state.server_hello()->version()); secure_renegotiation_check(state.server_hello()); @@ -516,7 +523,8 @@ void Client::process_handshake_msg(const Handshake_State* active_state, get_peer_cert_chain(state), session_ticket, m_info, - "" + "", + state.server_hello()->srtp_profile() ); const bool should_save = save_session(session_info); diff --git a/src/lib/tls/tls_extensions.cpp b/src/lib/tls/tls_extensions.cpp index 79a839187..29bf68b80 100644 --- a/src/lib/tls/tls_extensions.cpp +++ b/src/lib/tls/tls_extensions.cpp @@ -1,6 +1,6 @@ /* * TLS Extensions -* (C) 2011,2012 Jack Lloyd +* (C) 2011,2012,2015 Jack Lloyd * * Released under the terms of the Botan license */ @@ -39,6 +39,9 @@ Extension* make_extension(TLS_Data_Reader& reader, case TLSEXT_SIGNATURE_ALGORITHMS: return new Signature_Algorithms(reader, size); + case TLSEXT_USE_SRTP: + return new SRTP_Protection_Profiles(reader, size); + case TLSEXT_NEXT_PROTOCOL: return new Next_Protocol_Notification(reader, size); @@ -214,19 +217,21 @@ std::vector<byte> Renegotiation_Extension::serialize() const std::vector<byte> Maximum_Fragment_Length::serialize() const { - const std::map<size_t, byte> fragment_to_code = { { 512, 1 }, - { 1024, 2 }, - { 2048, 3 }, - { 4096, 4 } }; - - auto i = fragment_to_code.find(m_max_fragment); - - if(i == fragment_to_code.end()) - throw std::invalid_argument("Bad setting " + - std::to_string(m_max_fragment) + - " for maximum fragment size"); - - return std::vector<byte>(1, i->second); + switch(m_max_fragment) + { + case 512: + return std::vector<byte>(1, 1); + case 1024: + return std::vector<byte>(1, 2); + case 2048: + return std::vector<byte>(1, 3); + case 4096: + return std::vector<byte>(1, 4); + default: + throw std::invalid_argument("Bad setting " + + std::to_string(m_max_fragment) + + " for maximum fragment size"); + } } Maximum_Fragment_Length::Maximum_Fragment_Length(TLS_Data_Reader& reader, @@ -234,20 +239,23 @@ Maximum_Fragment_Length::Maximum_Fragment_Length(TLS_Data_Reader& reader, { if(extension_size != 1) throw Decoding_Error("Bad size for maximum fragment extension"); - byte val = reader.get_byte(); - - const std::map<byte, size_t> code_to_fragment = { { 1, 512 }, - { 2, 1024 }, - { 3, 2048 }, - { 4, 4096 } }; - - auto i = code_to_fragment.find(val); - if(i == code_to_fragment.end()) - throw TLS_Exception(Alert::ILLEGAL_PARAMETER, - "Bad value in maximum fragment extension"); + const byte val = reader.get_byte(); - m_max_fragment = i->second; + switch(val) + { + case 1: + m_max_fragment = 512; + case 2: + m_max_fragment = 1024; + case 3: + m_max_fragment = 2048; + case 4: + m_max_fragment = 4096; + default: + throw TLS_Exception(Alert::ILLEGAL_PARAMETER, + "Bad value " + std::to_string(val) + " for max fragment len"); + } } Next_Protocol_Notification::Next_Protocol_Notification(TLS_Data_Reader& reader, @@ -536,6 +544,39 @@ Session_Ticket::Session_Ticket(TLS_Data_Reader& reader, m_ticket = reader.get_elem<byte, std::vector<byte> >(extension_size); } +SRTP_Protection_Profiles::SRTP_Protection_Profiles(TLS_Data_Reader& reader, + u16bit extension_size) + { + m_pp = reader.get_range<u16bit>(2, 0, 65535); + + const std::vector<byte> mki = reader.get_range<byte>(1, 0, 255); + + if(m_pp.size() * 2 + mki.size() + 3 != extension_size) + throw Decoding_Error("Bad encoding for SRTP protection extension"); + + if(!mki.empty()) + throw Decoding_Error("Unhandled non-empty MKI for SRTP protection extension"); + } + +std::vector<byte> SRTP_Protection_Profiles::serialize() const + { + std::vector<byte> buf; + + const u16bit pp_len = m_pp.size() * 2; + buf.push_back(get_byte(0, pp_len)); + buf.push_back(get_byte(1, pp_len)); + + for(u16bit pp : m_pp) + { + buf.push_back(get_byte(0, pp)); + buf.push_back(get_byte(1, pp)); + } + + buf.push_back(0); // srtp_mki, always empty here + + return buf; + } + } } diff --git a/src/lib/tls/tls_extensions.h b/src/lib/tls/tls_extensions.h index ac1f75a2b..f26970b47 100644 --- a/src/lib/tls/tls_extensions.h +++ b/src/lib/tls/tls_extensions.h @@ -33,6 +33,7 @@ enum Handshake_Extension_Type { TLSEXT_EC_POINT_FORMATS = 11, TLSEXT_SRP_IDENTIFIER = 12, TLSEXT_SIGNATURE_ALGORITHMS = 13, + TLSEXT_USE_SRTP = 14, TLSEXT_HEARTBEAT_SUPPORT = 15, TLSEXT_SESSION_TICKET = 35, @@ -353,6 +354,32 @@ class Heartbeat_Support_Indicator : public Extension }; /** +* Used to indicate SRTP algorithms for DTLS (RFC 5764) +*/ +class SRTP_Protection_Profiles : public Extension + { + public: + static Handshake_Extension_Type static_type() + { return TLSEXT_USE_SRTP; } + + Handshake_Extension_Type type() const { return static_type(); } + + const std::vector<u16bit>& profiles() const { return m_pp; } + + std::vector<byte> serialize() const; + + bool empty() const { return m_pp.empty(); } + + SRTP_Protection_Profiles(const std::vector<u16bit>& pp) : m_pp(pp) {} + + SRTP_Protection_Profiles(u16bit pp) : m_pp(1, pp) {} + + SRTP_Protection_Profiles(TLS_Data_Reader& reader, u16bit extension_size); + private: + std::vector<u16bit> m_pp; + }; + +/** * Represents a block of extensions in a hello message */ class Extensions diff --git a/src/lib/tls/tls_messages.h b/src/lib/tls/tls_messages.h index 3083605e4..59bf296f4 100644 --- a/src/lib/tls/tls_messages.h +++ b/src/lib/tls/tls_messages.h @@ -1,6 +1,6 @@ /* * TLS Messages -* (C) 2004-2011 Jack Lloyd +* (C) 2004-2011,2015 Jack Lloyd * * Released under the terms of the Botan license */ @@ -27,6 +27,7 @@ class SRP6_Server_Session; namespace TLS { +class Session; class Handshake_IO; std::vector<byte> make_hello_random(RandomNumberGenerator& rng, @@ -150,6 +151,13 @@ class Client_Hello : public Handshake_Message return false; } + std::vector<u16bit> srtp_profiles() const + { + if(SRTP_Protection_Profiles* srtp = m_extensions.get<SRTP_Protection_Profiles>()) + return srtp->profiles(); + return std::vector<u16bit>(); + } + void update_hello_cookie(const Hello_Verify_Request& hello_verify); std::set<Handshake_Extension_Type> extension_types() const @@ -257,24 +265,44 @@ class Server_Hello : public Handshake_Message return false; } + u16bit srtp_profile() const + { + if(SRTP_Protection_Profiles* srtp = m_extensions.get<SRTP_Protection_Profiles>()) + { + auto prof = srtp->profiles(); + if(prof.size() != 1 || prof[0] == 0) + throw Decoding_Error("Server sent malformed DTLS-SRTP extension"); + return prof[0]; + } + + return 0; + } + std::set<Handshake_Extension_Type> extension_types() const { return m_extensions.extension_types(); } Server_Hello(Handshake_IO& io, Handshake_Hash& hash, const Policy& policy, - const std::vector<byte>& session_id, - Protocol_Version ver, + RandomNumberGenerator& rng, + const std::vector<byte>& secure_reneg_info, + const Client_Hello& client_hello, + const std::vector<byte>& new_session_id, + Protocol_Version new_session_version, u16bit ciphersuite, byte compression, - size_t max_fragment_size, - bool client_has_secure_renegotiation, - const std::vector<byte>& reneg_info, bool offer_session_ticket, - bool client_has_npn, - const std::vector<std::string>& next_protocols, - bool client_has_heartbeat, - RandomNumberGenerator& rng); + const std::vector<std::string>& next_protocols); + + Server_Hello(Handshake_IO& io, + Handshake_Hash& hash, + const Policy& policy, + RandomNumberGenerator& rng, + const std::vector<byte>& secure_reneg_info, + const Client_Hello& client_hello, + Session& resumed_session, + bool offer_session_ticket, + const std::vector<std::string>& next_protocols); Server_Hello(const std::vector<byte>& buf); private: diff --git a/src/lib/tls/tls_policy.cpp b/src/lib/tls/tls_policy.cpp index d0e227d2e..66b6490f0 100644 --- a/src/lib/tls/tls_policy.cpp +++ b/src/lib/tls/tls_policy.cpp @@ -87,14 +87,14 @@ std::vector<std::string> Policy::allowed_ecc_curves() const { return std::vector<std::string>({ "brainpool512r1", - "brainpool384r1", - "brainpool256r1", "secp521r1", + "brainpool384r1", "secp384r1", + "brainpool256r1", "secp256r1", - "secp256k1", - "secp224r1", - "secp224k1", + //"secp256k1", + //"secp224r1", + //"secp224k1", //"secp192r1", //"secp192k1", //"secp160r2", @@ -137,7 +137,7 @@ std::vector<byte> Policy::compression() const u32bit Policy::session_ticket_lifetime() const { - return 86400; // 1 day + return 86400; // ~1 day } bool Policy::send_fallback_scsv(Protocol_Version version) const @@ -148,8 +148,9 @@ bool Policy::send_fallback_scsv(Protocol_Version version) const bool Policy::acceptable_protocol_version(Protocol_Version version) const { if(version.is_datagram_protocol()) - return (version >= Protocol_Version::DTLS_V12); - return (version >= Protocol_Version::TLS_V10); + return (version >= Protocol_Version::DTLS_V10); + else + return (version >= Protocol_Version::TLS_V10); } Protocol_Version Policy::latest_supported_version(bool datagram) const @@ -175,6 +176,12 @@ bool Policy::allow_server_initiated_renegotiation() const return true; } +std::vector<u16bit> Policy::srtp_profiles() const + { + //return std::vector<u16bit>(); + return std::vector<u16bit>{1}; + } + namespace { class Ciphersuite_Preference_Ordering @@ -260,7 +267,7 @@ std::vector<u16bit> Policy::ciphersuite_list(Protocol_Version version, std::set<Ciphersuite, Ciphersuite_Preference_Ordering> ciphersuites(order); - for(auto suite : Ciphersuite::all_known_ciphersuites()) + for(auto&& suite : Ciphersuite::all_known_ciphersuites()) { if(!acceptable_ciphersuite(suite)) continue; diff --git a/src/lib/tls/tls_policy.h b/src/lib/tls/tls_policy.h index c3401b8cc..e08714df8 100644 --- a/src/lib/tls/tls_policy.h +++ b/src/lib/tls/tls_policy.h @@ -130,6 +130,13 @@ class BOTAN_DLL Policy virtual u32bit session_ticket_lifetime() const; /** + * If this returns a non-empty vector, and DTLS is negotiated, + * then we will also attempt to negotiate the SRTP extension from + * RFC 5764 using the returned values as the profile ids. + */ + virtual std::vector<u16bit> srtp_profiles() const; + + /** * @return true if and only if we are willing to accept this version * Default accepts TLS v1.0 and later. diff --git a/src/lib/tls/tls_server.cpp b/src/lib/tls/tls_server.cpp index 9b8a0d811..228668943 100644 --- a/src/lib/tls/tls_server.cpp +++ b/src/lib/tls/tls_server.cpp @@ -112,12 +112,8 @@ u16bit choose_ciphersuite( const Client_Hello* client_hello) { const bool our_choice = policy.server_uses_own_ciphersuite_preferences(); - - const bool have_srp = creds.attempt_srp("tls-server", - client_hello->sni_hostname()); - + const bool have_srp = creds.attempt_srp("tls-server", client_hello->sni_hostname()); const std::vector<u16bit> client_suites = client_hello->ciphersuites(); - const std::vector<u16bit> server_suites = policy.ciphersuite_list(version, have_srp); if(server_suites.empty()) @@ -381,31 +377,25 @@ void Server::process_handshake_msg(const Handshake_State* active_state, if(resuming) { - // resume session + // Only offer a resuming client a new ticket if they didn't send one this time, + // ie, resumed via server-side resumption. TODO: also send one if expiring soon? const bool offer_new_session_ticket = (state.client_hello()->supports_session_ticket() && state.client_hello()->session_ticket().empty() && have_session_ticket_key); - state.server_hello( - new Server_Hello( + state.server_hello(new Server_Hello( state.handshake_io(), state.hash(), m_policy, - state.client_hello()->session_id(), - Protocol_Version(session_info.version()), - session_info.ciphersuite_code(), - session_info.compression_method(), - session_info.fragment_size(), - state.client_hello()->secure_renegotiation(), + rng(), secure_renegotiation_data_for_server_hello(), + *state.client_hello(), + session_info, offer_new_session_ticket, - state.client_hello()->next_protocol_notification(), - m_possible_protocols, - state.client_hello()->supports_heartbeats(), - rng()) - ); + m_possible_protocols + )); secure_renegotiation_check(state.server_hello()); @@ -480,27 +470,19 @@ void Server::process_handshake_msg(const Handshake_State* active_state, send_alert(Alert(Alert::UNRECOGNIZED_NAME)); } - state.server_hello( - new Server_Hello( + state.server_hello(new Server_Hello( state.handshake_io(), state.hash(), m_policy, + rng(), + secure_renegotiation_data_for_server_hello(), + *state.client_hello(), make_hello_random(rng(), m_policy), // new session ID state.version(), - choose_ciphersuite(m_policy, - state.version(), - m_creds, - cert_chains, - state.client_hello()), + choose_ciphersuite(m_policy, state.version(), m_creds, cert_chains, state.client_hello()), choose_compression(m_policy, state.client_hello()->compression_methods()), - state.client_hello()->fragment_size(), - state.client_hello()->secure_renegotiation(), - secure_renegotiation_data_for_server_hello(), - state.client_hello()->supports_session_ticket() && have_session_ticket_key, - state.client_hello()->next_protocol_notification(), - m_possible_protocols, - state.client_hello()->supports_heartbeats(), - rng()) + have_session_ticket_key, + m_possible_protocols) ); secure_renegotiation_check(state.server_hello()); @@ -539,27 +521,19 @@ void Server::process_handshake_msg(const Handshake_State* active_state, } else { - state.server_kex( - new Server_Key_Exchange(state.handshake_io(), - state, - m_policy, - m_creds, - rng(), - private_key) - ); + state.server_kex(new Server_Key_Exchange(state.handshake_io(), + state, m_policy, + m_creds, rng(), private_key)); } - auto trusted_CAs = - m_creds.trusted_certificate_authorities("tls-server", sni_hostname); + auto trusted_CAs = m_creds.trusted_certificate_authorities("tls-server", sni_hostname); std::vector<X509_DN> client_auth_CAs; for(auto store : trusted_CAs) { auto subjects = store->all_subjects(); - client_auth_CAs.insert(client_auth_CAs.end(), - subjects.begin(), - subjects.end()); + client_auth_CAs.insert(client_auth_CAs.end(), subjects.begin(), subjects.end()); } if(!client_auth_CAs.empty() && state.ciphersuite().sig_algo() != "") @@ -684,7 +658,8 @@ void Server::process_handshake_msg(const Handshake_State* active_state, get_peer_cert_chain(state), std::vector<byte>(), Server_Information(state.client_hello()->sni_hostname()), - state.srp_identifier() + state.srp_identifier(), + state.server_hello()->srtp_profile() ); if(save_session(session_info)) diff --git a/src/lib/tls/tls_session.cpp b/src/lib/tls/tls_session.cpp index 37d6a2c67..5080d9f79 100644 --- a/src/lib/tls/tls_session.cpp +++ b/src/lib/tls/tls_session.cpp @@ -1,6 +1,6 @@ /* * TLS Session State -* (C) 2011-2012 Jack Lloyd +* (C) 2011-2012,2015 Jack Lloyd * * Released under the terms of the Botan license */ @@ -26,7 +26,8 @@ Session::Session(const std::vector<byte>& session_identifier, const std::vector<X509_Certificate>& certs, const std::vector<byte>& ticket, const Server_Information& server_info, - const std::string& srp_identifier) : + const std::string& srp_identifier, + u16bit srtp_profile) : m_start_time(std::chrono::system_clock::now()), m_identifier(session_identifier), m_session_ticket(ticket), @@ -35,6 +36,7 @@ Session::Session(const std::vector<byte>& session_identifier, m_ciphersuite(ciphersuite), m_compression_method(compression_method), m_connection_side(side), + m_srtp_profile(srtp_profile), m_fragment_size(fragment_size), m_peer_certs(certs), m_server_info(server_info), @@ -44,7 +46,7 @@ Session::Session(const std::vector<byte>& session_identifier, Session::Session(const std::string& pem) { - secure_vector<byte> der = PEM_Code::decode_check_label(pem, "SSL SESSION"); + secure_vector<byte> der = PEM_Code::decode_check_label(pem, "TLS SESSION"); *this = Session(&der[0], der.size()); } @@ -60,15 +62,15 @@ Session::Session(const byte ber[], size_t ber_len) ASN1_String srp_identifier_str; byte major_version = 0, minor_version = 0; - std::vector<byte> peer_cert_bits; size_t start_time = 0; + size_t srtp_profile = 0; BER_Decoder(ber, ber_len) .start_cons(SEQUENCE) .decode_and_check(static_cast<size_t>(TLS_SESSION_PARAM_STRUCT_VERSION), - "Unknown version in session structure") + "Unknown version in serialized TLS session") .decode_integer_type(start_time) .decode_integer_type(major_version) .decode_integer_type(minor_version) @@ -84,12 +86,14 @@ Session::Session(const byte ber[], size_t ber_len) .decode(server_service) .decode(server_port) .decode(srp_identifier_str) + .decode(srtp_profile) .end_cons() .verify_end(); m_version = Protocol_Version(major_version, minor_version); m_start_time = std::chrono::system_clock::from_time_t(start_time); m_connection_side = static_cast<Connection_Side>(side_code); + m_srtp_profile = srtp_profile; m_server_info = Server_Information(server_hostname.value(), server_service.value(), @@ -130,13 +134,14 @@ secure_vector<byte> Session::DER_encode() const .encode(ASN1_String(m_server_info.service(), UTF8_STRING)) .encode(static_cast<size_t>(m_server_info.port())) .encode(ASN1_String(m_srp_identifier, UTF8_STRING)) + .encode(static_cast<size_t>(m_srtp_profile)) .end_cons() .get_contents(); } std::string Session::PEM_encode() const { - return PEM_Code::encode(this->DER_encode(), "SSL SESSION"); + return PEM_Code::encode(this->DER_encode(), "TLS SESSION"); } std::chrono::seconds Session::session_age() const diff --git a/src/lib/tls/tls_session.h b/src/lib/tls/tls_session.h index 65154dfce..c3824237a 100644 --- a/src/lib/tls/tls_session.h +++ b/src/lib/tls/tls_session.h @@ -1,6 +1,6 @@ /* * TLS Session -* (C) 2011-2012 Jack Lloyd +* (C) 2011-2012,2015 Jack Lloyd * * Released under the terms of the Botan license */ @@ -53,7 +53,8 @@ class BOTAN_DLL Session const std::vector<X509_Certificate>& peer_certs, const std::vector<byte>& session_ticket, const Server_Information& server_info, - const std::string& srp_identifier); + const std::string& srp_identifier, + u16bit srtp_profile); /** * Load a session from DER representation (created by DER_encode) @@ -136,19 +137,17 @@ class BOTAN_DLL Session /** * Get the SRP identity (if sent by the client in the initial handshake) */ - std::string srp_identifier() const { return m_srp_identifier; } + const std::string& srp_identifier() const { return m_srp_identifier; } /** * Get the saved master secret */ - const secure_vector<byte>& master_secret() const - { return m_master_secret; } + const secure_vector<byte>& master_secret() const { return m_master_secret; } /** * Get the session identifier */ - const std::vector<byte>& session_id() const - { return m_identifier; } + const std::vector<byte>& session_id() const { return m_identifier; } /** * Get the negotiated maximum fragment size (or 0 if default) @@ -156,15 +155,19 @@ class BOTAN_DLL Session size_t fragment_size() const { return m_fragment_size; } /** + * Get the negotiated DTLS-SRTP algorithm (RFC 5764) + */ + u16bit dtls_srtp_profile() const { return m_srtp_profile; } + + /** * Return the certificate chain of the peer (possibly empty) */ - std::vector<X509_Certificate> peer_certs() const { return m_peer_certs; } + const std::vector<X509_Certificate>& peer_certs() const { return m_peer_certs; } /** * Get the wall clock time this session began */ - std::chrono::system_clock::time_point start_time() const - { return m_start_time; } + std::chrono::system_clock::time_point start_time() const { return m_start_time; } /** * Return how long this session has existed (in seconds) @@ -176,10 +179,10 @@ class BOTAN_DLL Session */ const std::vector<byte>& session_ticket() const { return m_session_ticket; } - Server_Information server_info() const { return m_server_info; } + const Server_Information& server_info() const { return m_server_info; } private: - enum { TLS_SESSION_PARAM_STRUCT_VERSION = 0x2994e301 }; + enum { TLS_SESSION_PARAM_STRUCT_VERSION = 20150104 }; std::chrono::system_clock::time_point m_start_time; @@ -191,6 +194,7 @@ class BOTAN_DLL Session u16bit m_ciphersuite; byte m_compression_method; Connection_Side m_connection_side; + u16bit m_srtp_profile; size_t m_fragment_size; |