aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorlloyd <[email protected]>2012-01-24 15:10:14 +0000
committerlloyd <[email protected]>2012-01-24 15:10:14 +0000
commit9e37cd76af978147cbb36faa09b9832b5f15f20a (patch)
tree5a198928294a9bde7b7cf5eb43aa5f89e885c25a /src
parent92f6a575bca25d8985aa87304e28cd63867310e2 (diff)
Send the supported elliptic curves extension. Instead of hardcoding
the values let policy specify them. Also choose an ECC curve for server kex from the client hello. Choice is via policy, default implementation is to choose the first curve the client supports out of the server's preference list.
Diffstat (limited to 'src')
-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