aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/tls/c_hello.cpp5
-rw-r--r--src/tls/s_hello.cpp7
-rw-r--r--src/tls/tls_extensions.cpp15
-rw-r--r--src/tls/tls_extensions.h3
-rw-r--r--src/tls/tls_messages.h5
-rw-r--r--src/tls/tls_policy.cpp31
-rw-r--r--src/tls/tls_policy.h10
-rw-r--r--src/tls/tls_server.cpp13
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