aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/manual/tls.rst9
-rw-r--r--src/lib/tls/msg_client_hello.cpp3
-rw-r--r--src/lib/tls/msg_server_hello.cpp98
-rw-r--r--src/lib/tls/tls_client.cpp10
-rw-r--r--src/lib/tls/tls_extensions.cpp93
-rw-r--r--src/lib/tls/tls_extensions.h27
-rw-r--r--src/lib/tls/tls_messages.h48
-rw-r--r--src/lib/tls/tls_policy.cpp25
-rw-r--r--src/lib/tls/tls_policy.h7
-rw-r--r--src/lib/tls/tls_server.cpp71
-rw-r--r--src/lib/tls/tls_session.cpp17
-rw-r--r--src/lib/tls/tls_session.h28
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;