aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRenĂ© Korthaus <[email protected]>2017-10-17 16:22:07 +0200
committerRenĂ© Korthaus <[email protected]>2017-10-17 16:49:57 +0200
commit824b2e56ca886585cc2dfd363bb1913c6d416904 (patch)
tree0de3aea53c9488bc1a1f90c0361d79c44a6f6f9b /src
parentf01f37d142ef230b03ca6af46f1e1a0615e4879a (diff)
Add supported groups TLS extension (RFC 7919)
Diffstat (limited to 'src')
-rw-r--r--src/lib/pubkey/dl_group/dl_named.cpp146
-rw-r--r--src/lib/tls/msg_client_hello.cpp16
-rw-r--r--src/lib/tls/msg_client_kex.cpp29
-rw-r--r--src/lib/tls/msg_server_kex.cpp5
-rw-r--r--src/lib/tls/tls_extensions.cpp81
-rw-r--r--src/lib/tls/tls_extensions.h20
-rw-r--r--src/lib/tls/tls_messages.h2
-rw-r--r--src/lib/tls/tls_policy.cpp51
-rw-r--r--src/lib/tls/tls_policy.h18
-rw-r--r--src/lib/tls/tls_server.cpp7
-rw-r--r--src/lib/tls/tls_text_policy.cpp5
-rw-r--r--src/tests/data/tls-policy/bsi.txt1
-rw-r--r--src/tests/data/tls-policy/suiteb.txt1
-rw-r--r--src/tests/data/tls/client_hello.vec8
-rw-r--r--src/tests/test_dl_group.cpp6
-rw-r--r--src/tests/unit_tls.cpp11
16 files changed, 372 insertions, 35 deletions
diff --git a/src/lib/pubkey/dl_group/dl_named.cpp b/src/lib/pubkey/dl_group/dl_named.cpp
index 4df9732be..fc5cf4fd2 100644
--- a/src/lib/pubkey/dl_group/dl_named.cpp
+++ b/src/lib/pubkey/dl_group/dl_named.cpp
@@ -354,6 +354,152 @@ std::string DL_Group::PEM_for_named_group(const std::string& name)
"eMFVkc39EVZP+I/zi3IdQjkv2kcyEtz9jS2IqXagCv/m//tDCjWeZMorNRyiQSOU"
"-----END DSA PARAMETERS-----";
+ if(name == "ffdhe/ietf/2048")
+ return
+ "-----BEGIN DSA PARAMETERS-----"
+ "MIICDAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz"
+ "+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a"
+ "87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7"
+ "YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi"
+ "7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD"
+ "ssbzSibBsu/6iGtCOGEoXJf//////////wKCAQB//////////9b8KixRXaVNV+4r"
+ "EBOennjsXOLB5xabStTwmyCKMhn95knO5xJNn3y+l/GxsYY67HtA2QFXYjC9ae+P"
+ "aur+srCSGfqPr4M3aEKxsqqe9o152quJrz+r5JrMJ4Y4cHNFu/FTRO159/Q5Dvis"
+ "UJtW85qYVmUnpB08vV4FWMFZkn2w6IRUpdlkcf3ctW1bsGv6NA6noVHvHKb6Vyt2"
+ "87G5XYyFg9PkdwU2uE8BfnDm+/F2YBoCZpQaF7DIuX9OdMLB/8cniRl3eUDB4f8d"
+ "jaY31rmd2v5eF2EQAuLHeMG+i0HZY3mlE2DZd/1ENaEcMJQuS///////////AgEC"
+ "-----END DSA PARAMETERS-----";
+
+ if(name == "ffdhe/ietf/3072")
+ return
+ "-----BEGIN DSA PARAMETERS-----"
+ "MIIDDAKCAYEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz"
+ "+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a"
+ "87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7"
+ "YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi"
+ "7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD"
+ "ssbzSibBsu/6iGtCOGEfz9zeNVs7ZRkDW7w09N75nAI4YbRvydbmyQd62R0mkff3"
+ "7lmMsPrBhtkcrv4TCYUTknC0EwyTvEN5RPT9RFLi103TZPLiHnH1S/9croKrnJ32"
+ "nuhtK8UiNjoNq8Uhl5sN6todv5pC1cRITgq80Gv6U93vPBsg7j/VnXwl5B0rZsYu"
+ "N///////////AoIBgH//////////1vwqLFFdpU1X7isQE56eeOxc4sHnFptK1PCb"
+ "IIoyGf3mSc7nEk2ffL6X8bGxhjrse0DZAVdiML1p749q6v6ysJIZ+o+vgzdoQrGy"
+ "qp72jXnaq4mvP6vkmswnhjhwc0W78VNE7Xn39DkO+KxQm1bzmphWZSekHTy9XgVY"
+ "wVmSfbDohFSl2WRx/dy1bVuwa/o0DqehUe8cpvpXK3bzsbldjIWD0+R3BTa4TwF+"
+ "cOb78XZgGgJmlBoXsMi5f050wsH/xyeJGXd5QMHh/x2NpjfWuZ3a/l4XYRAC4sd4"
+ "wb6LQdljeaUTYNl3/UQ1oRwwj+fubxqtnbKMga3eGnpvfM4BHDDaN+Trc2SDvWyO"
+ "k0j7+/csxlh9YMNsjld/CYTCick4WgmGSd4hvKJ6fqIpcWum6bJ5cQ84+qX/rldB"
+ "Vc5O+090NpXikRsdBtXikMvNhvVtDt/NIWriJCcFXmg1/Snu954NkHcf6s6+EvIO"
+ "lbNjFxv//////////wIBAg=="
+ "-----END DSA PARAMETERS-----";
+
+ if(name == "ffdhe/ietf/4096")
+ return
+ "-----BEGIN DSA PARAMETERS-----"
+ "MIIDDAKCAYEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz"
+ "+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a"
+ "87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7"
+ "YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi"
+ "7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD"
+ "ssbzSibBsu/6iGtCOGEfz9zeNVs7ZRkDW7w09N75nAI4YbRvydbmyQd62R0mkff3"
+ "7lmMsPrBhtkcrv4TCYUTknC0EwyTvEN5RPT9RFLi103TZPLiHnH1S/9croKrnJ32"
+ "nuhtK8UiNjoNq8Uhl5sN6todv5pC1cRITgq80Gv6U93vPBsg7j/VnXwl5B0rZsYu"
+ "N///////////AoIBgH//////////1vwqLFFdpU1X7isQE56eeOxc4sHnFptK1PCb"
+ "IIoyGf3mSc7nEk2ffL6X8bGxhjrse0DZAVdiML1p749q6v6ysJIZ+o+vgzdoQrGy"
+ "qp72jXnaq4mvP6vkmswnhjhwc0W78VNE7Xn39DkO+KxQm1bzmphWZSekHTy9XgVY"
+ "wVmSfbDohFSl2WRx/dy1bVuwa/o0DqehUe8cpvpXK3bzsbldjIWD0+R3BTa4TwF+"
+ "cOb78XZgGgJmlBoXsMi5f050wsH/xyeJGXd5QMHh/x2NpjfWuZ3a/l4XYRAC4sd4"
+ "wb6LQdljeaUTYNl3/UQ1oRwwj+fubxqtnbKMga3eGnpvfM4BHDDaN+Trc2SDvWyO"
+ "k0j7+/csxlh9YMNsjld/CYTCick4WgmGSd4hvKJ6fqIpcWum6bJ5cQ84+qX/rldB"
+ "Vc5O+090NpXikRsdBtXikMvNhvVtDt/NIWriJCcFXmg1/Snu954NkHcf6s6+EvIO"
+ "lbNjFxv//////////wIBAg=="
+ "-----END DSA PARAMETERS-----";
+
+ if(name == "ffdhe/ietf/6144")
+ return
+ "-----BEGIN DSA PARAMETERS-----"
+ "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"
+ "TmhyBzL//////////wIBAg=="
+ "-----END DSA PARAMETERS-----";
+
+ if(name == "ffdhe/ietf/8192")
+ return
+ "-----BEGIN DSA PARAMETERS-----"
+ "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"
+ "-----END DSA PARAMETERS-----";
+
return "";
}
diff --git a/src/lib/tls/msg_client_hello.cpp b/src/lib/tls/msg_client_hello.cpp
index bb7d84df8..e804a0cf0 100644
--- a/src/lib/tls/msg_client_hello.cpp
+++ b/src/lib/tls/msg_client_hello.cpp
@@ -121,9 +121,10 @@ Client_Hello::Client_Hello(Handshake_IO& io,
}
#endif
- m_extensions.add(new Supported_Elliptic_Curves(policy.allowed_ecc_curves()));
+ Supported_Groups* supported_groups = new Supported_Groups(policy.allowed_groups());
+ m_extensions.add(supported_groups);
- if(!policy.allowed_ecc_curves().empty())
+ if(!supported_groups->curves().empty())
{
m_extensions.add(new Supported_Point_Formats(policy.use_ecc_point_compression()));
}
@@ -324,8 +325,15 @@ std::set<std::string> Client_Hello::supported_sig_algos() const
std::vector<std::string> Client_Hello::supported_ecc_curves() const
{
- if(Supported_Elliptic_Curves* ecc = m_extensions.get<Supported_Elliptic_Curves>())
- return ecc->curves();
+ if(Supported_Groups* groups = m_extensions.get<Supported_Groups>())
+ return groups->curves();
+ return std::vector<std::string>();
+ }
+
+std::vector<std::string> Client_Hello::supported_dh_groups() const
+ {
+ if(Supported_Groups* groups = m_extensions.get<Supported_Groups>())
+ return groups->dh_groups();
return std::vector<std::string>();
}
diff --git a/src/lib/tls/msg_client_kex.cpp b/src/lib/tls/msg_client_kex.cpp
index 3291b6eb5..1c3950a03 100644
--- a/src/lib/tls/msg_client_kex.cpp
+++ b/src/lib/tls/msg_client_kex.cpp
@@ -101,6 +101,35 @@ Client_Key_Exchange::Client_Key_Exchange(Handshake_IO& io,
throw Decoding_Error("Bad params size for DH key exchange");
/*
+ * If we offer ffdhe groups in the client hello,
+ * p and g must match one of these groups.
+ */
+ std::vector<std::string> allowed_groups = policy.allowed_groups();
+ bool server_sent_requested_group = false;
+
+ if(!allowed_groups.empty())
+ {
+ for(const auto& allowed_group : allowed_groups)
+ {
+ if(Supported_Groups::is_dh_group(allowed_group))
+ {
+ DL_Group client_group(allowed_group);
+ if(client_group.get_p() == p && client_group.get_g() == g)
+ {
+ server_sent_requested_group = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if(!server_sent_requested_group)
+ {
+ throw TLS_Exception(Alert::INSUFFICIENT_SECURITY,
+ "Server sent unexpected DH key for DHE exchange");
+ }
+
+ /*
* A basic check for key validity. As we do not know q here we
* cannot check that Y is in the right subgroup. However since
* our key is ephemeral there does not seem to be any
diff --git a/src/lib/tls/msg_server_kex.cpp b/src/lib/tls/msg_server_kex.cpp
index 97ac4ac8f..0765e1bdc 100644
--- a/src/lib/tls/msg_server_kex.cpp
+++ b/src/lib/tls/msg_server_kex.cpp
@@ -56,7 +56,10 @@ Server_Key_Exchange::Server_Key_Exchange(Handshake_IO& io,
if(kex_algo == "DH" || kex_algo == "DHE_PSK")
{
- std::unique_ptr<DH_PrivateKey> dh(new DH_PrivateKey(rng, DL_Group(policy.dh_group())));
+ const std::vector<std::string>& dh_groups =
+ state.client_hello()->supported_dh_groups();
+
+ std::unique_ptr<DH_PrivateKey> dh(new DH_PrivateKey(rng, DL_Group(policy.choose_dh_group(dh_groups))));
append_tls_length_value(m_params, BigInt::encode(dh->get_domain().get_p()), 2);
append_tls_length_value(m_params, BigInt::encode(dh->get_domain().get_g()), 2);
diff --git a/src/lib/tls/tls_extensions.cpp b/src/lib/tls/tls_extensions.cpp
index 317d96b8d..8f13b2c6d 100644
--- a/src/lib/tls/tls_extensions.cpp
+++ b/src/lib/tls/tls_extensions.cpp
@@ -275,7 +275,23 @@ std::vector<uint8_t> Application_Layer_Protocol_Notification::serialize() const
return buf;
}
-std::string Supported_Elliptic_Curves::curve_id_to_name(uint16_t id)
+Supported_Groups::Supported_Groups(const std::vector<std::string>& groups) :
+ m_groups(groups)
+ {
+ for(const auto& group : m_groups)
+ {
+ if(is_dh_group(group))
+ {
+ m_dh_groups.push_back(group);
+ }
+ else
+ {
+ m_curves.push_back(group);
+ }
+ }
+ }
+
+std::string Supported_Groups::curve_id_to_name(uint16_t id)
{
switch(id)
{
@@ -302,12 +318,23 @@ std::string Supported_Elliptic_Curves::curve_id_to_name(uint16_t id)
return BOTAN_HOUSE_ECC_CURVE_NAME;
#endif
+ case 256:
+ return "ffdhe/ietf/2048";
+ case 257:
+ return "ffdhe/ietf/3072";
+ case 258:
+ return "ffdhe/ietf/4096";
+ case 259:
+ return "ffdhe/ietf/6144";
+ case 260:
+ return "ffdhe/ietf/8192";
+
default:
return ""; // something we don't know or support
}
}
-uint16_t Supported_Elliptic_Curves::name_to_curve_id(const std::string& name)
+uint16_t Supported_Groups::name_to_curve_id(const std::string& name)
{
if(name == "secp256r1")
return 23;
@@ -332,17 +359,39 @@ uint16_t Supported_Elliptic_Curves::name_to_curve_id(const std::string& name)
return BOTAN_HOUSE_ECC_CURVE_TLS_ID;
#endif
- // Unknown/unavailable EC curves are ignored
+ if(name == "ffdhe/ietf/2048")
+ return 256;
+ if(name == "ffdhe/ietf/3072")
+ return 257;
+ if(name == "ffdhe/ietf/4096")
+ return 258;
+ if(name == "ffdhe/ietf/6144")
+ return 259;
+ if(name == "ffdhe/ietf/8192")
+ return 260;
+
+ // Unknown/unavailable DH groups/EC curves are ignored
return 0;
}
-std::vector<uint8_t> Supported_Elliptic_Curves::serialize() const
+bool Supported_Groups::is_dh_group( const std::string& group_name )
+ {
+ if(group_name == "ffdhe/ietf/2048" || group_name == "ffdhe/ietf/3072"
+ || group_name == "ffdhe/ietf/4096" || group_name == "ffdhe/ietf/6144"
+ || group_name == "ffdhe/ietf/8192")
+ {
+ return true;
+ }
+ return false;
+ }
+
+std::vector<uint8_t> Supported_Groups::serialize() const
{
std::vector<uint8_t> buf(2);
- for(size_t i = 0; i != m_curves.size(); ++i)
+ for(size_t i = 0; i != m_groups.size(); ++i)
{
- const uint16_t id = name_to_curve_id(m_curves[i]);
+ const uint16_t id = name_to_curve_id(m_groups[i]);
if(id > 0)
{
@@ -357,16 +406,16 @@ std::vector<uint8_t> Supported_Elliptic_Curves::serialize() const
return buf;
}
-Supported_Elliptic_Curves::Supported_Elliptic_Curves(TLS_Data_Reader& reader,
- uint16_t extension_size)
+Supported_Groups::Supported_Groups(TLS_Data_Reader& reader,
+ uint16_t extension_size)
{
uint16_t len = reader.get_uint16_t();
if(len + 2 != extension_size)
- throw Decoding_Error("Inconsistent length field in elliptic curve list");
+ throw Decoding_Error("Inconsistent length field in supported groups list");
if(len % 2 == 1)
- throw Decoding_Error("Elliptic curve list of strange size");
+ throw Decoding_Error("Supported groups list of strange size");
len /= 2;
@@ -376,7 +425,17 @@ Supported_Elliptic_Curves::Supported_Elliptic_Curves(TLS_Data_Reader& reader,
const std::string name = curve_id_to_name(id);
if(!name.empty())
- m_curves.push_back(name);
+ {
+ m_groups.push_back(name);
+ if(is_dh_group(name))
+ {
+ m_dh_groups.push_back(name);
+ }
+ else
+ {
+ m_curves.push_back(name);
+ }
+ }
}
}
diff --git a/src/lib/tls/tls_extensions.h b/src/lib/tls/tls_extensions.h
index ee3310563..221d8b46f 100644
--- a/src/lib/tls/tls_extensions.h
+++ b/src/lib/tls/tls_extensions.h
@@ -225,10 +225,11 @@ class Session_Ticket final : public Extension
std::vector<uint8_t> m_ticket;
};
+
/**
-* Supported Elliptic Curves Extension (RFC 4492)
+* Supported Groups Extension (RFC 7919)
*/
-class Supported_Elliptic_Curves final : public Extension
+class Supported_Groups final : public Extension
{
public:
static Handshake_Extension_Type static_type()
@@ -239,21 +240,28 @@ class Supported_Elliptic_Curves final : public Extension
static std::string curve_id_to_name(uint16_t id);
static uint16_t name_to_curve_id(const std::string& name);
+ static bool is_dh_group( const std::string& group_name );
+
const std::vector<std::string>& curves() const { return m_curves; }
+ const std::vector<std::string>& dh_groups() const { return m_dh_groups; }
std::vector<uint8_t> serialize() const override;
- explicit Supported_Elliptic_Curves(const std::vector<std::string>& curves) :
- m_curves(curves) {}
+ explicit Supported_Groups(const std::vector<std::string>& groups);
- Supported_Elliptic_Curves(TLS_Data_Reader& reader,
+ Supported_Groups(TLS_Data_Reader& reader,
uint16_t extension_size);
- bool empty() const override { return m_curves.empty(); }
+ bool empty() const override { return m_groups.empty(); }
private:
+ std::vector<std::string> m_groups;
std::vector<std::string> m_curves;
+ std::vector<std::string> m_dh_groups;
};
+// previously Supported Elliptic Curves Extension (RFC 4492)
+using Supported_Elliptic_Curves = Supported_Groups;
+
/**
* Supported Point Formats Extension (RFC 4492)
*/
diff --git a/src/lib/tls/tls_messages.h b/src/lib/tls/tls_messages.h
index ac6c1e1ad..767635830 100644
--- a/src/lib/tls/tls_messages.h
+++ b/src/lib/tls/tls_messages.h
@@ -110,6 +110,8 @@ class BOTAN_UNSTABLE_API Client_Hello final : public Handshake_Message
std::vector<std::string> supported_ecc_curves() const;
+ std::vector<std::string> supported_dh_groups() const;
+
bool prefers_compressed_ec_points() const;
std::string sni_hostname() const;
diff --git a/src/lib/tls/tls_policy.cpp b/src/lib/tls/tls_policy.cpp
index 43926e314..0a7e78e65 100644
--- a/src/lib/tls/tls_policy.cpp
+++ b/src/lib/tls/tls_policy.cpp
@@ -10,6 +10,7 @@
#include <botan/tls_ciphersuite.h>
#include <botan/tls_magic.h>
#include <botan/tls_exceptn.h>
+#include <botan/tls_extensions.h>
#include <botan/internal/stl_util.h>
#include <botan/pk_keys.h>
#include <sstream>
@@ -117,7 +118,11 @@ std::vector<std::string> Policy::allowed_ecc_curves() const
bool Policy::allowed_ecc_curve(const std::string& curve) const
{
- return value_exists(allowed_ecc_curves(), curve);
+ if(!allowed_ecc_curves().empty())
+ {
+ return value_exists(allowed_ecc_curves(), curve);
+ }
+ return value_exists(allowed_groups(), curve);
}
bool Policy::use_ecc_point_compression() const
@@ -130,21 +135,56 @@ bool Policy::use_ecc_point_compression() const
*/
std::string Policy::choose_curve(const std::vector<std::string>& curve_names) const
{
- const std::vector<std::string> our_curves = allowed_ecc_curves();
+ const std::vector<std::string> our_groups = allowed_groups();
- for(size_t i = 0; i != our_curves.size(); ++i)
- if(value_exists(curve_names, our_curves[i]))
- return our_curves[i];
+ for(size_t i = 0; i != our_groups.size(); ++i)
+ if(!Supported_Groups::is_dh_group(our_groups[i])
+ && value_exists(curve_names, our_groups[i]))
+ return our_groups[i];
return ""; // no shared curve
}
+/*
+* Choose an FFDHE group to use
+*/
+std::string Policy::choose_dh_group(const std::vector<std::string>& dh_groups) const
+ {
+ const std::vector<std::string> our_groups = allowed_groups();
+
+ for(size_t i = 0; i != our_groups.size(); ++i)
+ if(Supported_Groups::is_dh_group(our_groups[i])
+ && value_exists(dh_groups, our_groups[i]))
+ return our_groups[i];
+
+ return ""; // no shared ffdhe group
+ }
+
std::string Policy::dh_group() const
{
// We offer 2048 bit DH because we can
return "modp/ietf/2048";
}
+std::vector<std::string> Policy::allowed_groups() const
+ {
+ // Default list is ordered by performance
+ return {
+ "x25519",
+ "secp256r1",
+ "secp521r1",
+ "secp384r1",
+ "brainpool256r1",
+ "brainpool384r1",
+ "brainpool512r1",
+ "ffdhe/ietf/2048",
+ "ffdhe/ietf/3072",
+ "ffdhe/ietf/4096",
+ "ffdhe/ietf/6144",
+ "ffdhe/ietf/8192"
+ };
+ }
+
size_t Policy::minimum_dh_group_size() const
{
return 2048;
@@ -502,6 +542,7 @@ void Policy::print(std::ostream& o) const
print_vec(o, "signature_methods", allowed_signature_methods());
print_vec(o, "key_exchange_methods", allowed_key_exchange_methods());
print_vec(o, "ecc_curves", allowed_ecc_curves());
+ print_vec(o, "groups", allowed_groups());
print_bool(o, "allow_insecure_renegotiation", allow_insecure_renegotiation());
print_bool(o, "include_time_in_hello_random", include_time_in_hello_random());
diff --git a/src/lib/tls/tls_policy.h b/src/lib/tls/tls_policy.h
index 333cf0ee1..2d90de5c0 100644
--- a/src/lib/tls/tls_policy.h
+++ b/src/lib/tls/tls_policy.h
@@ -103,6 +103,11 @@ class BOTAN_PUBLIC_API(2,0) Policy
virtual std::string choose_curve(const std::vector<std::string>& curve_names) const;
/**
+ * Choose an FFHDE group to use
+ */
+ virtual std::string choose_dh_group(const std::vector<std::string>& dh_group_names) const;
+
+ /**
* Allow renegotiation even if the counterparty doesn't
* support the secure renegotiation extension.
*
@@ -156,6 +161,8 @@ class BOTAN_PUBLIC_API(2,0) Policy
virtual std::string dh_group() const;
+ virtual std::vector<std::string> allowed_groups() const;
+
/**
* Return the minimum DH group size we're willing to use
* Default is currently 1024 (insecure), should be 2048
@@ -330,6 +337,9 @@ class BOTAN_PUBLIC_API(2,0) NSA_Suite_B_128 final : public Policy
std::vector<std::string> allowed_ecc_curves() const override
{ return std::vector<std::string>({"secp256r1"}); }
+ std::vector<std::string> allowed_groups() const override
+ { return allowed_ecc_curves(); }
+
size_t minimum_signature_strength() const override { return 128; }
bool allow_tls10() const override { return false; }
@@ -375,6 +385,12 @@ class BOTAN_PUBLIC_API(2,0) BSI_TR_02102_2 final : public Policy
return std::vector<std::string>({"brainpool512r1", "brainpool384r1", "brainpool256r1", "secp384r1", "secp256r1"});
}
+ std::vector<std::string> allowed_groups() const override
+ {
+ return std::vector<std::string>({"brainpool512r1", "brainpool384r1", "brainpool256r1", "secp384r1",
+ "secp256r1", "ffdhe/ietf/8192", "ffdhe/ietf/6144", "ffdhe/ietf/4096", "ffdhe/ietf/3072", "ffdhe/ietf/2048"});
+ }
+
bool allow_insecure_renegotiation() const override { return false; }
bool allow_server_initiated_renegotiation() const override { return true; }
bool server_uses_own_ciphersuite_preferences() const override { return true; }
@@ -451,6 +467,8 @@ class BOTAN_PUBLIC_API(2,0) Text_Policy : public Policy
std::vector<std::string> allowed_ecc_curves() const override;
+ std::vector<std::string> allowed_groups() const override;
+
bool use_ecc_point_compression() const override;
bool allow_tls10() const override;
diff --git a/src/lib/tls/tls_server.cpp b/src/lib/tls/tls_server.cpp
index c0e853a80..fb8317a1c 100644
--- a/src/lib/tls/tls_server.cpp
+++ b/src/lib/tls/tls_server.cpp
@@ -168,6 +168,9 @@ uint16_t choose_ciphersuite(
const bool have_shared_ecc_curve =
(policy.choose_curve(client_hello.supported_ecc_curves()) != "");
+ const bool have_shared_dh_group =
+ (policy.choose_dh_group(client_hello.supported_dh_groups()) != "");
+
/*
Walk down one list in preference order
*/
@@ -190,9 +193,13 @@ uint16_t choose_ciphersuite(
if(suite.valid() == false)
continue;
+ // TODO supported groups SHOULD have preference over ciphersuite list
if(suite.ecc_ciphersuite() && have_shared_ecc_curve == false)
continue;
+ if(suite.kex_algo() == "DH" && have_shared_dh_group == false)
+ continue;
+
// For non-anon ciphersuites
if(suite.sig_algo() != "")
{
diff --git a/src/lib/tls/tls_text_policy.cpp b/src/lib/tls/tls_text_policy.cpp
index ef5799339..345e6005f 100644
--- a/src/lib/tls/tls_text_policy.cpp
+++ b/src/lib/tls/tls_text_policy.cpp
@@ -108,6 +108,11 @@ std::string Text_Policy::dh_group() const
return get_str("dh_group", Policy::dh_group());
}
+std::vector<std::string> Text_Policy::allowed_groups() const
+ {
+ return get_list("groups", Policy::allowed_groups());
+ }
+
size_t Text_Policy::minimum_ecdh_group_size() const
{
return get_len("minimum_ecdh_group_size", Policy::minimum_ecdh_group_size());
diff --git a/src/tests/data/tls-policy/bsi.txt b/src/tests/data/tls-policy/bsi.txt
index 763c05219..9879b87f5 100644
--- a/src/tests/data/tls-policy/bsi.txt
+++ b/src/tests/data/tls-policy/bsi.txt
@@ -10,6 +10,7 @@ macs=AEAD SHA-384 SHA-256
key_exchange_methods=ECDH DH PSK ECDHE_PSK DHE_PSK
signature_methods=ECDSA RSA DSA
ecc_curves=brainpool512r1 brainpool384r1 brainpool256r1 secp384r1 secp256r1
+groups=brainpool512r1 brainpool384r1 brainpool256r1 secp384r1 secp256r1 ffdhe/ietf/8192 ffdhe/ietf/6144 ffdhe/ietf/4096 ffdhe/ietf/3072 ffdhe/ietf/2048
minimum_dh_group_size=2000
minimum_dsa_group_size=2000
minimum_ecdh_group_size=250
diff --git a/src/tests/data/tls-policy/suiteb.txt b/src/tests/data/tls-policy/suiteb.txt
index 51d8fec12..7c0b3e7d8 100644
--- a/src/tests/data/tls-policy/suiteb.txt
+++ b/src/tests/data/tls-policy/suiteb.txt
@@ -17,6 +17,7 @@ server_uses_own_ciphersuite_preferences = true
negotiate_encrypt_then_mac = true
session_ticket_lifetime = 86400
dh_group = modp/ietf/2048
+groups = secp256r1
minimum_dh_group_size = 2048
minimum_ecdh_group_size = 255
minimum_rsa_bits = 2048
diff --git a/src/tests/data/tls/client_hello.vec b/src/tests/data/tls/client_hello.vec
index aa8c03258..827f2ea4d 100644
--- a/src/tests/data/tls/client_hello.vec
+++ b/src/tests/data/tls/client_hello.vec
@@ -47,15 +47,15 @@ Buffer = 030320f3dc33f90be6509e6133a1819f2b80fe6ccc6268d9195ca4ead7504ffe7e2a000
Protocol = 0303
Exception = Invalid argument Decoding error: Bad extension size
-#invalid length of the elliptic curve extension (0xf01c instead of 0x001c)
+#invalid length of the supported groups extension (0xf01c instead of 0x001c)
Buffer = 0303871e18983024eaee1be8ae6607d5ecad941d33fd7fc1d8554a9e1fbfda8d30880000aac030c02cc028c024c014c00a00a500a300a1009f006b006a0069006800390038003700360088008700860085c032c02ec02ac026c00fc005009d003d00350084c02fc02bc027c023c013c00900a400a200a0009e00670040003f003e0033003200310030009a0099009800970045004400430042c031c02dc029c025c00ec004009c003c002f00960041c011c007c00cc00200050004c012c008001600130010000dc00dc003000a00ff01000055000b000403000102000af01c001a00170019001c001b0018001a0016000e000d000b000c0009000a00230000000d0020001e060106020603050105020503040104020403030103020303020102020203000f000101
Protocol = 0303
-Exception = Invalid argument Decoding error: Inconsistent length field in elliptic curve list
+Exception = Invalid argument Decoding error: Inconsistent length field in supported groups list
-#invalid length of the elliptic curve extension (0xf01a instead of 0x001a)
+#invalid length of the supported groups extension (0xf01a instead of 0x001a)
Buffer = 0303871e18983024eaee1be8ae6607d5ecad941d33fd7fc1d8554a9e1fbfda8d30880000aac030c02cc028c024c014c00a00a500a300a1009f006b006a0069006800390038003700360088008700860085c032c02ec02ac026c00fc005009d003d00350084c02fc02bc027c023c013c00900a400a200a0009e00670040003f003e0033003200310030009a0099009800970045004400430042c031c02dc029c025c00ec004009c003c002f00960041c011c007c00cc00200050004c012c008001600130010000dc00dc003000a00ff01000055000b000403000102000a001cf01a00170019001c001b0018001a0016000e000d000b000c0009000a00230000000d0020001e060106020603050105020503040104020403030103020303020102020203000f000101
Protocol = 0303
-Exception = Invalid argument Decoding error: Inconsistent length field in elliptic curve list
+Exception = Invalid argument Decoding error: Inconsistent length field in supported groups list
#invalid length of the session ticket extension
Buffer = 0303871e18983024eaee1be8ae6607d5ecad941d33fd7fc1d8554a9e1fbfda8d30880000aac030c02cc028c024c014c00a00a500a300a1009f006b006a0069006800390038003700360088008700860085c032c02ec02ac026c00fc005009d003d00350084c02fc02bc027c023c013c00900a400a200a0009e00670040003f003e0033003200310030009a0099009800970045004400430042c031c02dc029c025c00ec004009c003c002f00960041c011c007c00cc00200050004c012c008001600130010000dc00dc003000a00ff01000055000b000403000102000a001c001a00170019001c001b0018001a0016000e000d000b000c0009000a002300ff000d0020001e060106020603050105020503040104020403030103020303020102020203000f000101
diff --git a/src/tests/test_dl_group.cpp b/src/tests/test_dl_group.cpp
index baa2fdc9d..d402931c5 100644
--- a/src/tests/test_dl_group.cpp
+++ b/src/tests/test_dl_group.cpp
@@ -133,6 +133,12 @@ class DL_Group_Tests final : public Test
"dsa/jce/1024",
"dsa/botan/2048",
"dsa/botan/3072",
+
+ "ffdhe/ietf/2048",
+ "ffdhe/ietf/3072",
+ "ffdhe/ietf/4096",
+ "ffdhe/ietf/6144",
+ "ffdhe/ietf/8192",
};
Test::Result result("DL_Group named");
diff --git a/src/tests/unit_tls.cpp b/src/tests/unit_tls.cpp
index 6f25d6903..c181e5c92 100644
--- a/src/tests/unit_tls.cpp
+++ b/src/tests/unit_tls.cpp
@@ -1346,15 +1346,18 @@ class TLS_Unit_Tests final : public Test
test_modern_versions(results, *client_ses, *server_ses, *creds, "ECDH", "AES-128/GCM", "AEAD",
{ { "use_ecc_point_compression", "true" } });
test_modern_versions(results, *client_ses, *server_ses, *creds, "ECDH", "AES-256/GCM", "AEAD",
- { { "ecc_curves", "secp521r1" } });
+ { { "groups", "secp521r1" } });
test_modern_versions(results, *client_ses, *server_ses, *creds, "ECDH", "AES-128/GCM", "AEAD",
- { { "ecc_curves", "brainpool256r1" } });
+ { { "groups", "brainpool256r1" } });
#if defined(BOTAN_HAS_CURVE_25519)
test_modern_versions(results, *client_ses, *server_ses, *creds, "ECDH", "AES-128/GCM", "AEAD",
- { { "ecc_curves", "x25519" } });
+ { { "groups", "x25519" } });
#endif
+ test_modern_versions(results, *client_ses, *server_ses, *creds, "DH", "AES-128/GCM", "AEAD",
+ { { "groups", "ffdhe/ietf/2048" } });
+
std::unique_ptr<Botan::Credentials_Manager> creds_with_client_cert(create_creds(rng, true));
test_modern_versions(results, *client_ses, *server_ses, *creds_with_client_cert, "ECDH", "AES-256/GCM");
@@ -1388,7 +1391,7 @@ class TLS_Unit_Tests final : public Test
#if defined(BOTAN_HOUSE_ECC_CURVE_NAME)
test_modern_versions(results, *client_ses, *server_ses, *creds, "ECDH", "AES-128/GCM", "AEAD",
- { { "ecc_curves", BOTAN_HOUSE_ECC_CURVE_NAME } });
+ { { "groups", BOTAN_HOUSE_ECC_CURVE_NAME } });
#endif
return results;