diff options
author | lloyd <[email protected]> | 2015-01-04 17:43:34 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2015-01-04 17:43:34 +0000 |
commit | 8fcc2825c5aa7d6c359bba63eb883088a7650c86 (patch) | |
tree | 47d2f503ee43d57fe947d608e133ec06edf9d24c | |
parent | 5fb44f29a4b27905668d90a4ff46d882a41f5951 (diff) |
Add DTLS-SRTP key establishment from RFC 5764 (required for WebRTC).
Github issue 27.
Refactor server hello handling to make it easier to handle other extensions.
The manual specified that 224 bit NIST primes were disabled by default
for TLS but they were not. Additionaly disable the 256k1 curve and
reorder the remaining curves by size.
Rewrite the max fragment length extension code to roughly what an
ideal compiler would have turned the original code into, using a
switch instead of a lookup into a small constant std::map.
-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; |