diff options
-rw-r--r-- | doc/relnotes/1_11_3.rst | 7 | ||||
-rw-r--r-- | doc/tls.rst | 16 | ||||
-rw-r--r-- | src/tls/tls_policy.cpp | 8 | ||||
-rw-r--r-- | src/tls/tls_policy.h | 7 | ||||
-rw-r--r-- | src/tls/tls_server.cpp | 15 | ||||
-rw-r--r-- | src/tls/tls_version.h | 8 |
6 files changed, 54 insertions, 7 deletions
diff --git a/doc/relnotes/1_11_3.rst b/doc/relnotes/1_11_3.rst index 6b0ba1492..ac4de76aa 100644 --- a/doc/relnotes/1_11_3.rst +++ b/doc/relnotes/1_11_3.rst @@ -1,6 +1,13 @@ Version 1.11.3, Not Yet Released ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +* A new TLS policy mechanism + :cpp:func:`TLS::Policy::server_uses_own_ciphersuite_preferences` + controls how a server chooses a ciphersuite. Previously it always + chose its most preferred cipher out of the client's list, but this + can allow configuring a server to choose by the client's preferences + instead. + * Implementations of the OCB and GCM authenticated cipher modes are now included diff --git a/doc/tls.rst b/doc/tls.rst index 83503fcb1..406b94d93 100644 --- a/doc/tls.rst +++ b/doc/tls.rst @@ -526,17 +526,24 @@ be negotiated during a handshake. Default: "secp521r1", "secp384r1", "secp256r1", "secp256k1", "secp224r1", "secp224k1" - Also allowed: "secp192r1", "secp192k1", "secp160r2", "secp160r1", "secp160k1" + Also allowed: "secp192r1", "secp192k1", "secp160r2", "secp160r1", + "secp160k1" .. cpp:function:: std::vector<byte> compression() const Return the list of compression methods we are willing to use, in order of - preference. + preference. Default is null compression only. .. note:: TLS compression is not currently supported. + .. cpp:function:: bool server_uses_own_ciphersuite_preferences() const + + If this returns true, a server will pick the cipher it prefers the + most out of the client's list. Otherwise, it will negotiate the + first cipher in the client's ciphersuite list that it supports. + .. cpp:function:: bool negotiate_heartbeat_support() const If this function returns true, clients will offer the heartbeat @@ -545,6 +552,11 @@ be negotiated during a handshake. support and servers will ignore clients offering heartbeat support. + If this returns true, callers should expect to handle heartbeat + data in their ``proc_fn``. + + Default + .. cpp:function:: bool allow_server_initiated_renegotiation() const If this function returns true, a client will accept a diff --git a/src/tls/tls_policy.cpp b/src/tls/tls_policy.cpp index 98e3c6bca..1048e0a62 100644 --- a/src/tls/tls_policy.cpp +++ b/src/tls/tls_policy.cpp @@ -131,6 +131,14 @@ u32bit Policy::session_ticket_lifetime() const bool Policy::acceptable_protocol_version(Protocol_Version version) const { return version.known_version(); // accept any version we know about + + // maybe someday... + //return version >= Protocol_Version::TLS_V11; + } + +bool Policy::server_uses_own_ciphersuite_preferences() const + { + return true; } namespace { diff --git a/src/tls/tls_policy.h b/src/tls/tls_policy.h index 125faa665..7176f7fd5 100644 --- a/src/tls/tls_policy.h +++ b/src/tls/tls_policy.h @@ -126,6 +126,13 @@ class BOTAN_DLL Policy */ virtual bool acceptable_protocol_version(Protocol_Version version) const; + /** + * @return true if servers should choose the ciphersuite matching + * their highest preference, rather than the clients. + * Has no effect on client side. + */ + virtual bool server_uses_own_ciphersuite_preferences() const; + virtual ~Policy() {} }; diff --git a/src/tls/tls_server.cpp b/src/tls/tls_server.cpp index 2c393b32d..d8e827b39 100644 --- a/src/tls/tls_server.cpp +++ b/src/tls/tls_server.cpp @@ -112,6 +112,8 @@ u16bit choose_ciphersuite( const std::map<std::string, std::vector<X509_Certificate> >& cert_chains, 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()); @@ -128,12 +130,15 @@ u16bit choose_ciphersuite( const bool have_shared_ecc_curve = (policy.choose_curve(client_hello->supported_ecc_curves()) != ""); - // Ordering by our preferences rather than by clients - for(size_t i = 0; i != server_suites.size(); ++i) - { - const u16bit suite_id = server_suites[i]; + std::vector<u16bit> pref_list = server_suites; + std::vector<u16bit> other_list = client_suites; - if(!value_exists(client_suites, suite_id)) + if(!our_choice) + std::swap(pref_list, other_list); + + for(auto suite_id : pref_list) + { + if(!value_exists(other_list, suite_id)) continue; Ciphersuite suite = Ciphersuite::by_id(suite_id); diff --git a/src/tls/tls_version.h b/src/tls/tls_version.h index 39712db27..2fb5365dc 100644 --- a/src/tls/tls_version.h +++ b/src/tls/tls_version.h @@ -129,6 +129,14 @@ class BOTAN_DLL Protocol_Version */ bool operator>(const Protocol_Version& other) const; + /** + * @return if this version is later than or equal to other + */ + bool operator>=(const Protocol_Version& other) const + { + return (*this == other || *this > other); + } + private: u16bit m_version; }; |