From 99b781dfa607bc261ac7a009d6b278edb9d00e23 Mon Sep 17 00:00:00 2001 From: Xiangyu Bu Date: Tue, 18 Jul 2017 12:27:32 -0700 Subject: [PATCH] Functions to set common ciphers and sig algs for SSLContext. 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 | 78 ++++++++++++++++++++++++++ folly/io/async/SSLOptions.h | 66 ++++++++++++++++++++++ folly/io/async/test/SSLOptionsTest.cpp | 43 ++++++++++++++ 3 files changed, 187 insertions(+) create mode 100644 folly/io/async/SSLOptions.cpp create mode 100644 folly/io/async/SSLOptions.h create mode 100644 folly/io/async/test/SSLOptionsTest.cpp diff --git a/folly/io/async/SSLOptions.cpp b/folly/io/async/SSLOptions.cpp new file mode 100644 index 00000000..88e042e6 --- /dev/null +++ b/folly/io/async/SSLOptions.cpp @@ -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& SSLCommonOptions::getCipherList() { + static const std::vector 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& SSLCommonOptions::getSignatureAlgorithms() { + static const std::vector 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(ctx); + setSignatureAlgorithms(ctx); +} + +} // ssl +} // folly diff --git a/folly/io/async/SSLOptions.h b/folly/io/async/SSLOptions.h new file mode 100644 index 00000000..22ab52ed --- /dev/null +++ b/folly/io/async/SSLOptions.h @@ -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 +#include + +#include + +namespace folly { +namespace ssl { + +struct SSLCommonOptions { + /** + * Return the cipher list recommended for this options configuration. + */ + static const std::vector& getCipherList(); + + /** + * Return the list of signature algorithms recommended for this options + * configuration. + */ + static const std::vector& 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 +void setCipherSuites(SSLContext& ctx) { + try { + ctx.setCipherList(TSSLOptions::getCipherList()); + } catch (std::runtime_error const& e) { + LOG(DFATAL) << exceptionStr(e); + } +} + +template +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 index 00000000..f0c8f974 --- /dev/null +++ b/folly/io/async/test/SSLOptionsTest.cpp @@ -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 +#include +#include +#include + +using namespace std; +using namespace testing; + +namespace folly { + +class SSLOptionsTest : public testing::Test {}; + +void verifySSLCipherList(SSLContext& ctx, const vector& 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(ctx); + verifySSLCipherList(ctx, ssl::SSLCommonOptions::getCipherList()); +} +} -- 2.34.1