diff options
-rw-r--r-- | src/tls/c_hello.cpp | 5 | ||||
-rw-r--r-- | src/tls/s_hello.cpp | 7 | ||||
-rw-r--r-- | src/tls/tls_extensions.cpp | 15 | ||||
-rw-r--r-- | src/tls/tls_extensions.h | 3 | ||||
-rw-r--r-- | src/tls/tls_messages.h | 5 | ||||
-rw-r--r-- | src/tls/tls_policy.cpp | 31 | ||||
-rw-r--r-- | src/tls/tls_policy.h | 10 | ||||
-rw-r--r-- | src/tls/tls_server.cpp | 13 |
8 files changed, 66 insertions, 23 deletions
diff --git a/src/tls/c_hello.cpp b/src/tls/c_hello.cpp index 9e3824c57..7397f9122 100644 --- a/src/tls/c_hello.cpp +++ b/src/tls/c_hello.cpp @@ -99,6 +99,8 @@ Client_Hello::Client_Hello(Record_Writer& writer, std::vector<std::string> hashes = policy.allowed_hashes(); std::vector<std::string> sigs = policy.allowed_signature_methods(); + m_supported_curves = policy.allowed_ecc_curves(); + for(size_t i = 0; i != hashes.size(); ++i) for(size_t j = 0; j != sigs.size(); ++j) m_supported_algos.push_back(std::make_pair(hashes[i], sigs[j])); @@ -126,7 +128,7 @@ Client_Hello::Client_Hello(Record_Writer& writer, m_suites.push_back(session.ciphersuite_code()); m_comp_methods.push_back(session.compression_method()); - // set m_supported_algos here? + // set m_supported_algos + m_supported_curves here? send(writer, hash); } @@ -173,6 +175,7 @@ MemoryVector<byte> Client_Hello::serialize() const extensions.add(new Renegotation_Extension(m_renegotiation_info)); extensions.add(new Server_Name_Indicator(m_hostname)); extensions.add(new SRP_Identifier(m_srp_identifier)); + extensions.add(new Supported_Elliptic_Curves(m_supported_curves)); if(m_version >= Protocol_Version::TLS_V12) extensions.add(new Signature_Algorithms(m_supported_algos)); diff --git a/src/tls/s_hello.cpp b/src/tls/s_hello.cpp index 10e3a96fa..7b7e4a753 100644 --- a/src/tls/s_hello.cpp +++ b/src/tls/s_hello.cpp @@ -51,9 +51,10 @@ Server_Hello::Server_Hello(Record_Writer& writer, have_dsa = true; } - suite = policy.choose_suite(c_hello.ciphersuites(), - !c_hello.supported_ecc_curves().empty(), - have_rsa, have_dsa, false); + suite = policy.choose_suite( + c_hello.ciphersuites(), + policy.choose_curve(c_hello.supported_ecc_curves()) != "", + have_rsa, have_dsa, false); if(suite == 0) throw TLS_Exception(HANDSHAKE_FAILURE, diff --git a/src/tls/tls_extensions.cpp b/src/tls/tls_extensions.cpp index 8754405b0..20f687514 100644 --- a/src/tls/tls_extensions.cpp +++ b/src/tls/tls_extensions.cpp @@ -366,21 +366,6 @@ MemoryVector<byte> Supported_Elliptic_Curves::serialize() const return buf; } -Supported_Elliptic_Curves::Supported_Elliptic_Curves() - { - m_curves.push_back("secp521r1"); - m_curves.push_back("secp384r1"); - m_curves.push_back("secp256r1"); - m_curves.push_back("secp256k1"); - m_curves.push_back("secp224r1"); - m_curves.push_back("secp224k1"); - m_curves.push_back("secp192r1"); - m_curves.push_back("secp192k1"); - m_curves.push_back("secp160r2"); - m_curves.push_back("secp160r1"); - m_curves.push_back("secp160k1"); - } - Supported_Elliptic_Curves::Supported_Elliptic_Curves(TLS_Data_Reader& reader, u16bit extension_size) { diff --git a/src/tls/tls_extensions.h b/src/tls/tls_extensions.h index cad9ad41c..36c41c9a5 100644 --- a/src/tls/tls_extensions.h +++ b/src/tls/tls_extensions.h @@ -208,7 +208,8 @@ class Supported_Elliptic_Curves : public Extension MemoryVector<byte> serialize() const; - Supported_Elliptic_Curves(); // default values, for client + Supported_Elliptic_Curves(const std::vector<std::string>& curves) : + m_curves(curves) {} Supported_Elliptic_Curves(TLS_Data_Reader& reader, u16bit extension_size); diff --git a/src/tls/tls_messages.h b/src/tls/tls_messages.h index ec2229c21..33cd9e493 100644 --- a/src/tls/tls_messages.h +++ b/src/tls/tls_messages.h @@ -60,10 +60,11 @@ class Client_Hello : public Handshake_Message return v; } - std::vector<std::pair<std::string, std::string> > supported_algos() const + const std::vector<std::pair<std::string, std::string> >& supported_algos() const { return m_supported_algos; } - const std::vector<std::string> supported_ecc_curves() const { return m_supported_curves; } + const std::vector<std::string>& supported_ecc_curves() const + { return m_supported_curves; } std::vector<u16bit> ciphersuites() const { return m_suites; } std::vector<byte> compression_methods() const { return m_comp_methods; } diff --git a/src/tls/tls_policy.cpp b/src/tls/tls_policy.cpp index bdcebab71..c0ce15641 100644 --- a/src/tls/tls_policy.cpp +++ b/src/tls/tls_policy.cpp @@ -56,6 +56,23 @@ std::vector<std::string> Policy::allowed_signature_methods() const return allowed; } +std::vector<std::string> Policy::allowed_ecc_curves() const + { + std::vector<std::string> curves; + curves.push_back("secp521r1"); + curves.push_back("secp384r1"); + curves.push_back("secp256r1"); + curves.push_back("secp256k1"); + curves.push_back("secp224r1"); + curves.push_back("secp224k1"); + curves.push_back("secp192r1"); + curves.push_back("secp192k1"); + curves.push_back("secp160r2"); + curves.push_back("secp160r1"); + curves.push_back("secp160k1"); + return curves; + } + namespace { class Ciphersuite_Preference_Ordering @@ -179,6 +196,20 @@ std::vector<byte> Policy::compression() const } /* +* Choose an ECC curve to use +*/ +std::string Policy::choose_curve(const std::vector<std::string>& curve_names) const + { + std::vector<std::string> our_curves; + + for(size_t i = 0; i != our_curves.size(); ++i) + if(value_exists(curve_names, our_curves[i])) + return our_curves[i]; + + return ""; // no shared curve + } + +/* * Choose which ciphersuite to use */ u16bit Policy::choose_suite(const std::vector<u16bit>& client_suites, diff --git a/src/tls/tls_policy.h b/src/tls/tls_policy.h index 50793c899..6b7387f46 100644 --- a/src/tls/tls_policy.h +++ b/src/tls/tls_policy.h @@ -54,6 +54,11 @@ class BOTAN_DLL Policy virtual std::vector<std::string> allowed_signature_methods() const; /** + * Return list of ECC curves we are willing to use in order of preference + */ + virtual std::vector<std::string> allowed_ecc_curves() const; + + /** * Returns a list of signature algorithms we are willing to use, * in order of preference. Allowed values any value of * Compression_Method. @@ -61,6 +66,11 @@ class BOTAN_DLL Policy virtual std::vector<byte> compression() const; /** + * Choose an elliptic curve to use + */ + virtual std::string choose_curve(const std::vector<std::string>& curve_names) const; + + /** * Require support for RFC 5746 extensions to enable * renegotiation. * diff --git a/src/tls/tls_server.cpp b/src/tls/tls_server.cpp index 47c62a96a..207d40990 100644 --- a/src/tls/tls_server.cpp +++ b/src/tls/tls_server.cpp @@ -265,7 +265,18 @@ void Server::process_handshake_msg(Handshake_Type type, state->kex_priv = new DH_PrivateKey(rng, policy.dh_group()); else if(kex_algo == "ECDH") { - EC_Group ec_group("secp256r1"); // FIXME, use client known groups + const std::vector<std::string>& curves = + state->client_hello->supported_ecc_curves(); + + if(curves.empty()) + throw Internal_Error("Client sent no ECC extension but we negotiated ECDH"); + + const std::string curve_name = policy.choose_curve(curves); + + if(curve_name == "") // shouldn't happen + throw Internal_Error("Could not agree on an ECC curve with the client"); + + EC_Group ec_group(curve_name); state->kex_priv = new ECDH_PrivateKey(rng, ec_group); } else |