diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/tls/msg_client_hello.cpp | 10 | ||||
-rw-r--r-- | src/lib/tls/msg_server_hello.cpp | 8 | ||||
-rw-r--r-- | src/lib/tls/tls_client.cpp | 3 | ||||
-rw-r--r-- | src/lib/tls/tls_extensions.cpp | 19 | ||||
-rw-r--r-- | src/lib/tls/tls_extensions.h | 24 | ||||
-rw-r--r-- | src/lib/tls/tls_messages.h | 10 | ||||
-rw-r--r-- | src/lib/tls/tls_server.cpp | 21 | ||||
-rw-r--r-- | src/lib/tls/tls_session.cpp | 4 | ||||
-rw-r--r-- | src/lib/tls/tls_session.h | 7 | ||||
-rw-r--r-- | src/lib/tls/tls_session_key.cpp | 24 |
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); } |