You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by ti...@apache.org on 2017/07/27 00:51:35 UTC

[1/2] mesos git commit: Added documentation for LIBPROCESS_SSL_ECDH_CURVE environment variable.

Repository: mesos
Updated Branches:
  refs/heads/master 6827a4839 -> fc27129a1


Added documentation for LIBPROCESS_SSL_ECDH_CURVE environment variable.

This adds the adequate documentation entry for the new
`LIBPROCESS_SSL_ECDH_CURVE` environment variable, which allow the
configuration of ECDHE key exchange while establishing TLS sessions.

Review: https://reviews.apache.org/r/60996/


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/fc27129a
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/fc27129a
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/fc27129a

Branch: refs/heads/master
Commit: fc27129a1f63fb48da5ed41b82c150be2ce45121
Parents: 6790669
Author: Alexander Rojas <al...@mesosphere.io>
Authored: Thu Jul 27 00:43:22 2017 +0200
Committer: Till Toenshoff <to...@me.com>
Committed: Thu Jul 27 02:51:16 2017 +0200

----------------------------------------------------------------------
 docs/ssl.md | 4 ++++
 1 file changed, 4 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/fc27129a/docs/ssl.md
----------------------------------------------------------------------
diff --git a/docs/ssl.md b/docs/ssl.md
index 811390f..e6c1181 100644
--- a/docs/ssl.md
+++ b/docs/ssl.md
@@ -74,6 +74,10 @@ The above switches enable / disable the specified protocols. By default only TLS
 _SSLv2 is disabled completely because modern versions of OpenSSL disable it using multiple compile time configuration options._
 #<a name="Dependencies"></a>Dependencies
 
+#### LIBPROCESS_SSL_ECDH_CURVE=(auto|list of curves separated by ':') [default=auto]
+List of elliptic curves which should be used for ECDHE-based cipher suites, in preferred order. Available values depend on the OpenSSL version used. Default value `auto` allows OpenSSL to pick the curve automatically.
+OpenSSL versions prior to `1.0.2` allow for the use of only one curve; in those cases, `auto` defaults to `prime256v1`.
+
 ### libevent
 We require the OpenSSL support from libevent. The suggested version of libevent is [`2.0.22-stable`](https://github.com/libevent/libevent/releases/tag/release-2.0.22-stable). As new releases come out we will try to maintain compatibility.
 


[2/2] mesos git commit: Added support for OpenSSL's ECDH key exchange.

Posted by ti...@apache.org.
Added support for OpenSSL's ECDH key exchange.

This patch adds the configuration necessary so that the Elliptic Curve
Diffie Hellman algorithm can be used for TLS key exchange if the
OpenSSL version used supports it.

It also adds the SSL flag `LIBPROCESS_SSL_ECDH_CURVES` which allows
for the specification of a specific elliptic curve (or set of curves).

Users will need to specify the TLS cipher suite that uses ECDH in order
to enable the new key exchange. By default Mesos does not use any ECDH
cipher suites.

Support for ephemeral ECDH public keys is the default, so that new
public keys are generated for each exchange.

Note that in order to enable ECDSA ciphers an ECDSA key is still
necessary instead of the more traditional RSA one.

Review: https://reviews.apache.org/r/60913/


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/67906696
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/67906696
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/67906696

Branch: refs/heads/master
Commit: 679066964ac4c0e34208cb583ac9bbf31cbc3102
Parents: 6827a48
Author: Alexander Rojas <al...@mesosphere.io>
Authored: Thu Jul 27 00:42:21 2017 +0200
Committer: Till Toenshoff <to...@me.com>
Committed: Thu Jul 27 02:51:16 2017 +0200

----------------------------------------------------------------------
 .../libprocess/include/process/ssl/flags.hpp    |  1 +
 3rdparty/libprocess/src/openssl.cpp             | 81 ++++++++++++++++++++
 3rdparty/libprocess/src/openssl.hpp             |  1 +
 3rdparty/libprocess/src/tests/ssl_tests.cpp     | 43 +++++++++++
 4 files changed, 126 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/67906696/3rdparty/libprocess/include/process/ssl/flags.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/include/process/ssl/flags.hpp b/3rdparty/libprocess/include/process/ssl/flags.hpp
index 13fa7a0..3806266 100644
--- a/3rdparty/libprocess/include/process/ssl/flags.hpp
+++ b/3rdparty/libprocess/include/process/ssl/flags.hpp
@@ -45,6 +45,7 @@ public:
   Option<std::string> ca_dir;
   Option<std::string> ca_file;
   std::string ciphers;
+  std::string ecdh_curves;
   bool enable_ssl_v3;
   bool enable_tls_v1_0;
   bool enable_tls_v1_1;

http://git-wip-us.apache.org/repos/asf/mesos/blob/67906696/3rdparty/libprocess/src/openssl.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/openssl.cpp b/3rdparty/libprocess/src/openssl.cpp
index e6f17e4..22f073e 100644
--- a/3rdparty/libprocess/src/openssl.cpp
+++ b/3rdparty/libprocess/src/openssl.cpp
@@ -115,6 +115,16 @@ Flags::Flags()
       "AES128-SHA:AES256-SHA:RC4-SHA:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:"
       "DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA");
 
+  add(&Flags::ecdh_curves,
+      "ecdh_curves",
+      "Colon separated list of curve NID or names, e.g. 'P-521:P-384:P-256'. "
+      "The curves are in preference order. If no list is provided, the most "
+      "appropriate curve for a client will be selected. This behavior can be "
+      "explicitly enabled by setting this flag to 'auto'."
+      "NOTE: Old versions of OpenSSL support only one curve, check "
+      "the documentation of your OpenSSL.",
+      "auto");
+
   // We purposely don't have a flag for SSLv2. We do this because most
   // systems have disabled SSLv2 at compilation due to having so many
   // security vulnerabilities.
@@ -281,6 +291,70 @@ string error_string(unsigned long code)
 }
 
 
+#if OPENSSL_VERSION_NUMBER >= 0x0090800fL && !defined(OPENSSL_NO_ECDH)
+// Sets the elliptic curve parameters for the given context in order
+// to enable ECDH ciphers.
+// Adapted from NGINX SSL initialization code:
+// https://github.com/nginx/nginx/blob/bfe36ba3185a477d2f8ce120577308646173b736/
+// src/event/ngx_event_openssl.c#L1080-L1161
+static Try<Nothing> initialize_ecdh_curve(SSL_CTX* ctx, const Flags& ssl_flags)
+{
+#if defined(SSL_OP_SINGLE_ECDH_USE)
+  // Let OpenSSL compute new ECDH parameters for each new handshake.
+  // In newer versions (1.0.2+) of OpenSSL this is the default, and
+  // this call has no effect.
+  SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE);
+#endif // SSL_OP_SINGLE_ECDH_USE
+
+#if (defined SSL_CTX_set1_curves_list || defined SSL_CTRL_SET_CURVES_LIST)
+  // If `SSL_CTX_set_ecdh_auto` is not defined, OpenSSL will ignore the
+  // preference order of the curve list and use its own algorithm to chose
+  // the right curve for a connection.
+#if defined(SSL_CTX_set_ecdh_auto)
+  SSL_CTX_set_ecdh_auto(ctx, 1);
+#endif // SSL_CTX_set_ecdh_auto
+
+  if (ssl_flags.ecdh_curves == "auto") {
+    return Nothing();
+  }
+
+  if (SSL_CTX_set1_curves_list(ctx, ssl_flags.ecdh_curves.c_str()) != 1) {
+    unsigned long error = ERR_get_error();
+    return Error(
+        "Could not load ECDH curves '" + ssl_flags.ecdh_curves + "' " +
+        "(OpenSSL error #" + stringify(error) + "): " + error_string(error));
+  }
+
+  VLOG(2) << "Using ecdh curves: " << ssl_flags.ecdh_curves;
+#else // SSL_CTX_set1_curves_list || SSL_CTRL_SET_CURVES_LIST
+  string curve =
+      ssl_flags.ecdh_curves == "auto" ? "prime256v1" : ssl_flags.ecdh_curves;
+
+  int nid = OBJ_sn2nid(curve.c_str());
+  if (nid == 0) {
+    unsigned long error = ERR_get_error();
+    return Error(
+        "Unknown curve '" + curve + "' (OpenSSL error #" + stringify(error) +
+        "): " + error_string(error));
+  }
+
+  EC_KEY* ecdh = EC_KEY_new_by_curve_name(nid);
+  if (ecdh == nullptr) {
+    unsigned long error = ERR_get_error();
+    return Error(
+        "Error generating key from curve " + curve + "' (OpenSSL error #" +
+        stringify(error) + "): " + error_string(error));
+  }
+
+  SSL_CTX_set_tmp_ecdh(ctx, ecdh);
+  EC_KEY_free(ecdh);
+
+  VLOG(2) << "Using ecdh curve: " << ssl_flags.ecdh_curves;
+#endif // SSL_CTX_set1_curves_list || SSL_CTRL_SET_CURVES_LIST
+  return Nothing();
+}
+#endif // OPENSSL_VERSION_NUMBER >= 0x0090800fL && !OPENSSL_NO_ECDH
+
 // Tests can declare this function and use it to re-configure the SSL
 // environment variables programatically. Without explicitly declaring
 // this function, it is not visible. This is the preferred behavior as
@@ -593,6 +667,13 @@ void reinitialize()
   if (!ssl_flags->enable_tls_v1_2) { ssl_options |= SSL_OP_NO_TLSv1_2; }
 
   SSL_CTX_set_options(ctx, ssl_options);
+
+#if OPENSSL_VERSION_NUMBER >= 0x0090800fL && !defined(OPENSSL_NO_ECDH)
+  Try<Nothing> ecdh_initialized = initialize_ecdh_curve(ctx, *ssl_flags);
+  if (ecdh_initialized.isError()) {
+    EXIT(EXIT_FAILURE) << ecdh_initialized.error();
+  }
+#endif // OPENSSL_VERSION_NUMBER >= 0x0090800fL && !OPENSSL_NO_ECDH
 }
 
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/67906696/3rdparty/libprocess/src/openssl.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/openssl.hpp b/3rdparty/libprocess/src/openssl.hpp
index 7ded2c7..e74db5f 100644
--- a/3rdparty/libprocess/src/openssl.hpp
+++ b/3rdparty/libprocess/src/openssl.hpp
@@ -45,6 +45,7 @@ namespace openssl {
 //    LIBPROCESS_SSL_ENABLE_TLS_V1_0=(false|0,true|1)
 //    LIBPROCESS_SSL_ENABLE_TLS_V1_1=(false|0,true|1)
 //    LIBPROCESS_SSL_ENABLE_TLS_V1_2=(false|0,true|1)
+//    LIBPROCESS_SSL_ECDH_CURVES=(auto|list of curves separated by ':')
 //
 // TODO(benh): When/If we need to support multiple contexts in the
 // same process, for example for Server Name Indication (SNI), then

http://git-wip-us.apache.org/repos/asf/mesos/blob/67906696/3rdparty/libprocess/src/tests/ssl_tests.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/tests/ssl_tests.cpp b/3rdparty/libprocess/src/tests/ssl_tests.cpp
index 8a14dcb..6affda8 100644
--- a/3rdparty/libprocess/src/tests/ssl_tests.cpp
+++ b/3rdparty/libprocess/src/tests/ssl_tests.cpp
@@ -528,6 +528,49 @@ TEST_F(SSLTest, ProtocolMismatch)
 }
 
 
+// Ensure that key exchange using ECDHE algorithm works.
+TEST_F(SSLTest, ECDHESupport)
+{
+  // Set up the default server environment variables.
+  map<string, string> server_environment = {
+    {"LIBPROCESS_SSL_ENABLED", "true"},
+    {"LIBPROCESS_SSL_KEY_FILE", key_path().string()},
+    {"LIBPROCESS_SSL_CERT_FILE", certificate_path().string()},
+    {"LIBPROCESS_SSL_CIPHERS",
+     "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:"
+     "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA"}
+  };
+
+  // Set up the default client environment variables.
+  map<string, string> client_environment = {
+    {"LIBPROCESS_SSL_ENABLED", "true"},
+    {"LIBPROCESS_SSL_KEY_FILE", key_path().string()},
+    {"LIBPROCESS_SSL_CERT_FILE", certificate_path().string()},
+    {"LIBPROCESS_SSL_CIPHERS",
+     "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:"
+     "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA"}
+  };
+
+  // Set up the server.
+  Try<Socket> server = setup_server(server_environment);
+  ASSERT_SOME(server);
+
+  // Launch the client.
+  Try<Subprocess> client =
+      launch_client(client_environment, server.get(), true);
+  ASSERT_SOME(client);
+
+  Future<Socket> socket = server.get().accept();
+  AWAIT_ASSERT_READY(socket);
+
+  // TODO(jmlvanre): Remove const copy.
+  AWAIT_ASSERT_EQ(data, Socket(socket.get()).recv());
+  AWAIT_ASSERT_READY(Socket(socket.get()).send(data));
+
+  AWAIT_ASSERT_READY(await_subprocess(client.get(), 0));
+}
+
+
 // Ensure we can communicate between a POLL based socket and an SSL
 // socket if 'SSL_SUPPORT_DOWNGRADE' is enabled.
 TEST_F(SSLTest, ValidDowngrade)