Functions to set common ciphers and sig algs for SSLContext.
authorXiangyu Bu <xbu@fb.com>
Tue, 18 Jul 2017 19:27:32 +0000 (12:27 -0700)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Tue, 18 Jul 2017 19:39:31 +0000 (12:39 -0700)
Summary:
This diff contains some helper functions that set a `SSLContext` object with recommended
lists of ciphers and signature algorithms for given scenarios. In addition, DES and CHACHA are removed from the cipher list.

Reviewed By: yfeldblum

Differential Revision: D5373599

fbshipit-source-id: 04de11fe90cac734caa12a80e56f70532803f94e

folly/io/async/SSLOptions.cpp [new file with mode: 0644]
folly/io/async/SSLOptions.h [new file with mode: 0644]
folly/io/async/test/SSLOptionsTest.cpp [new file with mode: 0644]

diff --git a/folly/io/async/SSLOptions.cpp b/folly/io/async/SSLOptions.cpp
new file mode 100644 (file)
index 0000000..88e042e
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2004-present Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "SSLOptions.h"
+
+namespace folly {
+namespace ssl {
+
+const std::vector<std::string>& SSLCommonOptions::getCipherList() {
+  static const std::vector<std::string> kCommonCipherList = {
+      "ECDHE-ECDSA-AES128-GCM-SHA256",
+      "ECDHE-RSA-AES128-GCM-SHA256",
+      "ECDHE-ECDSA-AES256-GCM-SHA384",
+      "ECDHE-RSA-AES256-GCM-SHA384",
+      "ECDHE-ECDSA-AES256-SHA",
+      "ECDHE-RSA-AES256-SHA",
+      "ECDHE-ECDSA-AES128-SHA",
+      "ECDHE-RSA-AES128-SHA",
+      "ECDHE-RSA-AES256-SHA384",
+      "AES128-GCM-SHA256",
+      "AES256-SHA",
+      "AES128-SHA",
+  };
+  return kCommonCipherList;
+}
+
+const std::vector<std::string>& SSLCommonOptions::getSignatureAlgorithms() {
+  static const std::vector<std::string> kCommonSigAlgs = {
+      "RSA+SHA512",
+      "ECDSA+SHA512",
+      "RSA+SHA384",
+      "ECDSA+SHA384",
+      "RSA+SHA256",
+      "ECDSA+SHA256",
+      "RSA+SHA1",
+      "ECDSA+SHA1",
+  };
+  return kCommonSigAlgs;
+}
+
+void SSLCommonOptions::setClientOptions(SSLContext& ctx) {
+#ifdef SSL_MODE_HANDSHAKE_CUTTHROUGH
+  ctx.enableFalseStart();
+#endif
+
+  X509VerifyParam param(X509_VERIFY_PARAM_new());
+  X509_VERIFY_PARAM_set_flags(param.get(), X509_V_FLAG_X509_STRICT);
+  try {
+    ctx.setX509VerifyParam(param);
+  } catch (std::runtime_error const& e) {
+    LOG(DFATAL) << exceptionStr(e);
+  }
+
+  try {
+    ctx.setClientECCurvesList({"P-256", "P-384"});
+  } catch (std::runtime_error const& e) {
+    LOG(DFATAL) << exceptionStr(e);
+  }
+
+  setCipherSuites<SSLCommonOptions>(ctx);
+  setSignatureAlgorithms<SSLCommonOptions>(ctx);
+}
+
+} // ssl
+} // folly
diff --git a/folly/io/async/SSLOptions.h b/folly/io/async/SSLOptions.h
new file mode 100644 (file)
index 0000000..22ab52e
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2004-present Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <folly/Format.h>
+#include <folly/io/async/SSLContext.h>
+
+#include <glog/logging.h>
+
+namespace folly {
+namespace ssl {
+
+struct SSLCommonOptions {
+  /**
+   * Return the cipher list recommended for this options configuration.
+   */
+  static const std::vector<std::string>& getCipherList();
+
+  /**
+   * Return the list of signature algorithms recommended for this options
+   * configuration.
+   */
+  static const std::vector<std::string>& getSignatureAlgorithms();
+
+  /**
+   * Set common parameters on a client SSL context, for example,
+   * ciphers, signature algorithms, verification options, and client EC curves.
+   * @param ctx The SSL Context to which to apply the options.
+   */
+  static void setClientOptions(SSLContext& ctx);
+};
+
+template <typename TSSLOptions>
+void setCipherSuites(SSLContext& ctx) {
+  try {
+    ctx.setCipherList(TSSLOptions::getCipherList());
+  } catch (std::runtime_error const& e) {
+    LOG(DFATAL) << exceptionStr(e);
+  }
+}
+
+template <typename TSSLOptions>
+void setSignatureAlgorithms(SSLContext& ctx) {
+  try {
+    ctx.setSignatureAlgorithms(TSSLOptions::getSignatureAlgorithms());
+  } catch (std::runtime_error const& e) {
+    LOG(DFATAL) << exceptionStr(e);
+  }
+}
+
+} // ssl
+} // folly
diff --git a/folly/io/async/test/SSLOptionsTest.cpp b/folly/io/async/test/SSLOptionsTest.cpp
new file mode 100644 (file)
index 0000000..f0c8f97
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2004-present Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <folly/io/async/SSLContext.h>
+#include <folly/io/async/SSLOptions.h>
+#include <folly/portability/GTest.h>
+#include <folly/ssl/OpenSSLPtrTypes.h>
+
+using namespace std;
+using namespace testing;
+
+namespace folly {
+
+class SSLOptionsTest : public testing::Test {};
+
+void verifySSLCipherList(SSLContext& ctx, const vector<string>& ciphers) {
+  int i = 0;
+  ssl::SSLUniquePtr ssl(ctx.createSSL());
+  for (auto& cipher : ciphers) {
+    ASSERT_STREQ(cipher.c_str(), SSL_get_cipher_list(ssl.get(), i++));
+  }
+  ASSERT_EQ(nullptr, SSL_get_cipher_list(ssl.get(), i));
+}
+
+TEST_F(SSLOptionsTest, TestSetCommonCipherList) {
+  SSLContext ctx;
+  ssl::setCipherSuites<ssl::SSLCommonOptions>(ctx);
+  verifySSLCipherList(ctx, ssl::SSLCommonOptions::getCipherList());
+}
+}