aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/tls
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/tls')
-rw-r--r--src/lib/tls/msg_client_hello.cpp10
-rw-r--r--src/lib/tls/msg_server_hello.cpp8
-rw-r--r--src/lib/tls/tls_client.cpp3
-rw-r--r--src/lib/tls/tls_extensions.cpp19
-rw-r--r--src/lib/tls/tls_extensions.h24
-rw-r--r--src/lib/tls/tls_messages.h10
-rw-r--r--src/lib/tls/tls_server.cpp21
-rw-r--r--src/lib/tls/tls_session.cpp4
-rw-r--r--src/lib/tls/tls_session.h7
-rw-r--r--src/lib/tls/tls_session_key.cpp24
10 files changed, 118 insertions, 12 deletions
diff --git a/src/lib/tls/msg_client_hello.cpp b/src/lib/tls/msg_client_hello.cpp
index ce20d6781..fffb321d6 100644
--- a/src/lib/tls/msg_client_hello.cpp
+++ b/src/lib/tls/msg_client_hello.cpp
@@ -1,6 +1,6 @@
/*
* TLS Hello Request and Client Hello Messages
-* (C) 2004-2011,2015 Jack Lloyd
+* (C) 2004-2011,2015,2016 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
@@ -80,6 +80,7 @@ Client_Hello::Client_Hello(Handshake_IO& io,
m_suites(policy.ciphersuite_list(m_version, (srp_identifier != ""))),
m_comp_methods(policy.compression())
{
+ m_extensions.add(new Extended_Master_Secret);
m_extensions.add(new Renegotiation_Extension(reneg_info));
m_extensions.add(new SRP_Identifier(srp_identifier));
m_extensions.add(new Server_Name_Indicator(hostname));
@@ -130,6 +131,13 @@ Client_Hello::Client_Hello(Handshake_IO& io,
if(!value_exists(m_comp_methods, session.compression_method()))
m_comp_methods.push_back(session.compression_method());
+ /*
+ We always add the EMS extension, even if not used in the original session.
+ If the server understands it and follows the RFC it should reject our resume
+ attempt and upgrade us to a new session with the EMS protection.
+ */
+ m_extensions.add(new Extended_Master_Secret);
+
m_extensions.add(new Renegotiation_Extension(reneg_info));
m_extensions.add(new SRP_Identifier(session.srp_identifier()));
m_extensions.add(new Server_Name_Indicator(session.server_info().hostname()));
diff --git a/src/lib/tls/msg_server_hello.cpp b/src/lib/tls/msg_server_hello.cpp
index ba7eee3d9..25d53b81b 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,2015 Jack Lloyd
+* (C) 2004-2011,2015,2016 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
@@ -35,6 +35,9 @@ Server_Hello::Server_Hello(Handshake_IO& io,
m_ciphersuite(ciphersuite),
m_comp_method(compression)
{
+ if(client_hello.supports_extended_master_secret())
+ m_extensions.add(new Extended_Master_Secret);
+
if(client_hello.secure_renegotiation())
m_extensions.add(new Renegotiation_Extension(reneg_info));
@@ -90,6 +93,9 @@ Server_Hello::Server_Hello(Handshake_IO& io,
m_ciphersuite(resumed_session.ciphersuite_code()),
m_comp_method(resumed_session.compression_method())
{
+ if(client_hello.supports_extended_master_secret())
+ m_extensions.add(new Extended_Master_Secret);
+
if(client_hello.secure_renegotiation())
m_extensions.add(new Renegotiation_Extension(reneg_info));
diff --git a/src/lib/tls/tls_client.cpp b/src/lib/tls/tls_client.cpp
index 82630b7fa..623a52225 100644
--- a/src/lib/tls/tls_client.cpp
+++ b/src/lib/tls/tls_client.cpp
@@ -1,6 +1,6 @@
/*
* TLS Client
-* (C) 2004-2011,2012,2015 Jack Lloyd
+* (C) 2004-2011,2012,2015,2016 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
@@ -510,6 +510,7 @@ void Client::process_handshake_msg(const Handshake_State* active_state,
state.server_hello()->compression_method(),
CLIENT,
state.server_hello()->fragment_size(),
+ state.server_hello()->supports_extended_master_secret(),
get_peer_cert_chain(state),
session_ticket,
m_info,
diff --git a/src/lib/tls/tls_extensions.cpp b/src/lib/tls/tls_extensions.cpp
index 06efebb4b..cedf390e6 100644
--- a/src/lib/tls/tls_extensions.cpp
+++ b/src/lib/tls/tls_extensions.cpp
@@ -1,6 +1,6 @@
/*
* TLS Extensions
-* (C) 2011,2012,2015 Jack Lloyd
+* (C) 2011,2012,2015,2016 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
@@ -39,12 +39,15 @@ Extension* make_extension(TLS_Data_Reader& reader,
case TLSEXT_SIGNATURE_ALGORITHMS:
return new Signature_Algorithms(reader, size);
- case TLSEXT_USE_SRTP:
+ case TLSEXT_USE_SRTP:
return new SRTP_Protection_Profiles(reader, size);
case TLSEXT_ALPN:
return new Application_Layer_Protocol_Notification(reader, size);
+ case TLSEXT_EXTENDED_MASTER_SECRET:
+ return new Extended_Master_Secret(reader, size);
+
case TLSEXT_HEARTBEAT_SUPPORT:
return new Heartbeat_Support_Indicator(reader, size);
@@ -598,6 +601,18 @@ std::vector<byte> SRTP_Protection_Profiles::serialize() const
return buf;
}
+Extended_Master_Secret::Extended_Master_Secret(TLS_Data_Reader&,
+ u16bit extension_size)
+ {
+ if(extension_size != 0)
+ throw Decoding_Error("Invalid extended_master_secret extension");
+ }
+
+std::vector<byte> Extended_Master_Secret::serialize() const
+ {
+ return std::vector<byte>();
+ }
+
}
}
diff --git a/src/lib/tls/tls_extensions.h b/src/lib/tls/tls_extensions.h
index 7527b5cdd..d7d8ab380 100644
--- a/src/lib/tls/tls_extensions.h
+++ b/src/lib/tls/tls_extensions.h
@@ -1,6 +1,6 @@
/*
* TLS Extensions
-* (C) 2011-2012 Jack Lloyd
+* (C) 2011,2012,2016 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
@@ -37,6 +37,8 @@ enum Handshake_Extension_Type {
TLSEXT_HEARTBEAT_SUPPORT = 15,
TLSEXT_ALPN = 16,
+ TLSEXT_EXTENDED_MASTER_SECRET = 23,
+
TLSEXT_SESSION_TICKET = 35,
TLSEXT_SAFE_RENEGOTIATION = 65281,
@@ -375,6 +377,26 @@ class SRTP_Protection_Profiles : public Extension
};
/**
+* Extended Master Secret Extension (RFC 7627)
+*/
+class Extended_Master_Secret : public Extension
+ {
+ public:
+ static Handshake_Extension_Type static_type()
+ { return TLSEXT_EXTENDED_MASTER_SECRET; }
+
+ Handshake_Extension_Type type() const override { return static_type(); }
+
+ std::vector<byte> serialize() const override;
+
+ bool empty() const override { return false; }
+
+ Extended_Master_Secret() {}
+
+ Extended_Master_Secret(TLS_Data_Reader& reader, u16bit extension_size);
+ };
+
+/**
* 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 7a556a61c..e771bac0c 100644
--- a/src/lib/tls/tls_messages.h
+++ b/src/lib/tls/tls_messages.h
@@ -138,6 +138,11 @@ class Client_Hello : public Handshake_Message
return m_extensions.has<Application_Layer_Protocol_Notification>();
}
+ bool supports_extended_master_secret() const
+ {
+ return m_extensions.has<Extended_Master_Secret>();
+ }
+
std::vector<std::string> next_protocols() const
{
if(auto alpn = m_extensions.get<Application_Layer_Protocol_Notification>())
@@ -239,6 +244,11 @@ class Server_Hello : public Handshake_Message
return 0;
}
+ bool supports_extended_master_secret() const
+ {
+ return m_extensions.has<Extended_Master_Secret>();
+ }
+
bool supports_session_ticket() const
{
return m_extensions.has<Session_Ticket>();
diff --git a/src/lib/tls/tls_server.cpp b/src/lib/tls/tls_server.cpp
index 774827346..76db9ce6b 100644
--- a/src/lib/tls/tls_server.cpp
+++ b/src/lib/tls/tls_server.cpp
@@ -1,6 +1,6 @@
/*
* TLS Server
-* (C) 2004-2011,2012 Jack Lloyd
+* (C) 2004-2011,2012,2016 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
@@ -98,6 +98,24 @@ bool check_for_resume(Session& session_info,
return false;
}
+ // Checking extended_master_secret on resume (RFC 7627 section 5.3)
+ if(client_hello->supports_extended_master_secret() != session_info.supports_extended_master_secret())
+ {
+ if(!session_info.supports_extended_master_secret())
+ {
+ return false; // force new handshake with extended master secret
+ }
+ else
+ {
+ /*
+ Client previously negotiated session with extended master secret,
+ but has now attempted to resume without the extension: abort
+ */
+ throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
+ "Client resumed extended ms session without sending extension");
+ }
+ }
+
return true;
}
@@ -648,6 +666,7 @@ void Server::process_handshake_msg(const Handshake_State* active_state,
state.server_hello()->compression_method(),
SERVER,
state.server_hello()->fragment_size(),
+ state.server_hello()->supports_extended_master_secret(),
get_peer_cert_chain(state),
std::vector<byte>(),
Server_Information(state.client_hello()->sni_hostname()),
diff --git a/src/lib/tls/tls_session.cpp b/src/lib/tls/tls_session.cpp
index 7089a70f0..dbdb99ac8 100644
--- a/src/lib/tls/tls_session.cpp
+++ b/src/lib/tls/tls_session.cpp
@@ -24,6 +24,7 @@ Session::Session(const std::vector<byte>& session_identifier,
byte compression_method,
Connection_Side side,
size_t fragment_size,
+ bool extended_master_secret,
const std::vector<X509_Certificate>& certs,
const std::vector<byte>& ticket,
const Server_Information& server_info,
@@ -38,6 +39,7 @@ Session::Session(const std::vector<byte>& session_identifier,
m_compression_method(compression_method),
m_connection_side(side),
m_srtp_profile(srtp_profile),
+ m_extended_master_secret(extended_master_secret),
m_fragment_size(fragment_size),
m_peer_certs(certs),
m_server_info(server_info),
@@ -81,6 +83,7 @@ Session::Session(const byte ber[], size_t ber_len)
.decode_integer_type(m_compression_method)
.decode_integer_type(side_code)
.decode_integer_type(m_fragment_size)
+ .decode(m_extended_master_secret)
.decode(m_master_secret, OCTET_STRING)
.decode(peer_cert_bits, OCTET_STRING)
.decode(server_hostname)
@@ -129,6 +132,7 @@ secure_vector<byte> Session::DER_encode() const
.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_extended_master_secret)
.encode(m_master_secret, OCTET_STRING)
.encode(peer_cert_bits, OCTET_STRING)
.encode(ASN1_String(m_server_info.hostname(), UTF8_STRING))
diff --git a/src/lib/tls/tls_session.h b/src/lib/tls/tls_session.h
index 81c662507..f38ca8e27 100644
--- a/src/lib/tls/tls_session.h
+++ b/src/lib/tls/tls_session.h
@@ -38,6 +38,7 @@ class BOTAN_DLL Session
m_compression_method(0),
m_connection_side(static_cast<Connection_Side>(0)),
m_srtp_profile(0),
+ m_extended_master_secret(false),
m_fragment_size(0)
{}
@@ -51,6 +52,7 @@ class BOTAN_DLL Session
byte compression_method,
Connection_Side side,
size_t fragment_size,
+ bool supports_extended_master_secret,
const std::vector<X509_Certificate>& peer_certs,
const std::vector<byte>& session_ticket,
const Server_Information& server_info,
@@ -160,6 +162,8 @@ class BOTAN_DLL Session
*/
u16bit dtls_srtp_profile() const { return m_srtp_profile; }
+ bool supports_extended_master_secret() const { return m_extended_master_secret; }
+
/**
* Return the certificate chain of the peer (possibly empty)
*/
@@ -183,7 +187,7 @@ class BOTAN_DLL Session
const Server_Information& server_info() const { return m_server_info; }
private:
- enum { TLS_SESSION_PARAM_STRUCT_VERSION = 20150104 };
+ enum { TLS_SESSION_PARAM_STRUCT_VERSION = 20160103 };
std::chrono::system_clock::time_point m_start_time;
@@ -196,6 +200,7 @@ class BOTAN_DLL Session
byte m_compression_method;
Connection_Side m_connection_side;
u16bit m_srtp_profile;
+ bool m_extended_master_secret;
size_t m_fragment_size;
diff --git a/src/lib/tls/tls_session_key.cpp b/src/lib/tls/tls_session_key.cpp
index 574b6940b..ffadf3e33 100644
--- a/src/lib/tls/tls_session_key.cpp
+++ b/src/lib/tls/tls_session_key.cpp
@@ -1,6 +1,6 @@
/*
* TLS Session Key
-* (C) 2004-2006,2011 Jack Lloyd
+* (C) 2004-2006,2011,2016 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
@@ -24,11 +24,17 @@ Session_Keys::Session_Keys(const Handshake_State* state,
const size_t mac_keylen = state->ciphersuite().mac_keylen();
const size_t cipher_nonce_bytes = state->ciphersuite().nonce_bytes_from_handshake();
+ const bool extended_master_secret = state->server_hello()->supports_extended_master_secret();
+
const size_t prf_gen = 2 * (mac_keylen + cipher_keylen + cipher_nonce_bytes);
const byte MASTER_SECRET_MAGIC[] = {
0x6D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74 };
+ const byte EXT_MASTER_SECRET_MAGIC[] = {
+ 0x65, 0x78, 0x74, 0x65, 0x6E, 0x64, 0x65, 0x64, 0x20,
+ 0x6D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74 };
+
const byte KEY_GEN_MAGIC[] = {
0x6B, 0x65, 0x79, 0x20, 0x65, 0x78, 0x70, 0x61, 0x6E, 0x73, 0x69, 0x6F, 0x6E };
@@ -36,14 +42,24 @@ Session_Keys::Session_Keys(const Handshake_State* state,
if(resuming)
{
+ // This is actually the master secret saved as part of the session
master_sec = pre_master_secret;
}
else
{
secure_vector<byte> salt;
- salt += std::make_pair(MASTER_SECRET_MAGIC, sizeof(MASTER_SECRET_MAGIC));
- salt += state->client_hello()->random();
- salt += state->server_hello()->random();
+ if(extended_master_secret)
+ {
+ salt += std::make_pair(EXT_MASTER_SECRET_MAGIC, sizeof(EXT_MASTER_SECRET_MAGIC));
+ salt += state->hash().final(state->version(),
+ state->ciphersuite().prf_algo());
+ }
+ else
+ {
+ salt += std::make_pair(MASTER_SECRET_MAGIC, sizeof(MASTER_SECRET_MAGIC));
+ salt += state->client_hello()->random();
+ salt += state->server_hello()->random();
+ }
master_sec = prf->derive_key(48, pre_master_secret, salt);
}