diff options
| author | Tobias Markmann <tm@ayena.de> | 2018-03-09 15:40:22 (GMT) | 
|---|---|---|
| committer | Tobias Markmann <tm@ayena.de> | 2018-03-12 09:43:10 (GMT) | 
| commit | 863c72980c9c25c81ef8864b310e1fd9cb9a57df (patch) | |
| tree | caf4a4cdd801f4a8d39062757f6985292884a376 | |
| parent | ff600776577ce4e3bbf9aa66f5980bc9cf1042a0 (diff) | |
| download | swift-863c72980c9c25c81ef8864b310e1fd9cb9a57df.zip swift-863c72980c9c25c81ef8864b310e1fd9cb9a57df.tar.bz2 | |
Ability to set Diffie-Hellman parameters for OpenSSLContext
Test-Information:
Unit tests pass on macOS 10.13.3 with ASAN and Clang 7.0.
Change-Id: Ifc2bf2c1b63fca7f3ee43ef61c79a96b8e5ced5f
| -rw-r--r-- | Swiften/TLS/OpenSSL/OpenSSLContext.cpp | 28 | ||||
| -rw-r--r-- | Swiften/TLS/OpenSSL/OpenSSLContext.h | 1 | ||||
| -rw-r--r-- | Swiften/TLS/OpenSSL/OpenSSLContextFactory.cpp | 26 | ||||
| -rw-r--r-- | Swiften/TLS/OpenSSL/OpenSSLContextFactory.h | 2 | ||||
| -rw-r--r-- | Swiften/TLS/TLSContext.cpp | 5 | ||||
| -rw-r--r-- | Swiften/TLS/TLSContext.h | 1 | ||||
| -rw-r--r-- | Swiften/TLS/TLSContextFactory.cpp | 7 | ||||
| -rw-r--r-- | Swiften/TLS/TLSContextFactory.h | 3 | ||||
| -rw-r--r-- | Swiften/TLS/UnitTest/ClientServerTest.cpp | 80 | 
9 files changed, 153 insertions, 0 deletions
| diff --git a/Swiften/TLS/OpenSSL/OpenSSLContext.cpp b/Swiften/TLS/OpenSSL/OpenSSLContext.cpp index 6c27e22..6cbd303 100644 --- a/Swiften/TLS/OpenSSL/OpenSSLContext.cpp +++ b/Swiften/TLS/OpenSSL/OpenSSLContext.cpp @@ -14,6 +14,8 @@  #include <memory>  #include <vector> + +#include <openssl/bio.h>  #include <openssl/err.h>  #include <openssl/pkcs12.h> @@ -93,6 +95,13 @@ OpenSSLContext::OpenSSLContext(Mode mode) : mode_(mode), state_(State::Start) {      SSL_CTX_set_options(context_.get(), SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);      if (mode_ == Mode::Server) { +#if OPENSSL_VERSION_NUMBER < 0x1010 +        // Automatically select highest preference curve used for ECDH temporary keys used during +        // key exchange if possible. +        // Since version 1.1.0, this option is always enabled. +        SSL_CTX_set_ecdh_auto(context_.get(), 1); +#endif +          SSL_CTX_set_tlsext_servername_arg(context_.get(), this);          SSL_CTX_set_tlsext_servername_callback(context_.get(), OpenSSLContext::handleServerNameCallback);      } @@ -465,6 +474,25 @@ bool OpenSSLContext::setClientCertificate(CertificateWithKey::ref certificate) {      return true;  } +bool OpenSSLContext::setDiffieHellmanParameters(const ByteArray& parametersInOpenSslDer) { +    auto bio = std::unique_ptr<BIO, decltype(&BIO_free)>(BIO_new(BIO_s_mem()), BIO_free); +    if (bio) { +        BIO_write(bio.get(), vecptr(parametersInOpenSslDer), parametersInOpenSslDer.size()); +        auto result = 0L; +        if (auto dhparams = d2i_DHparams_bio(bio.get(), NULL)) { +            if (handle_) { +                result = SSL_set_tmp_dh(handle_.get(), dhparams); +            } +            else { +                result = SSL_CTX_set_tmp_dh(context_.get(), dhparams); +            } +            DH_free(dhparams); +        } +        return result == 1; +    } +    return false; +} +  std::vector<Certificate::ref> OpenSSLContext::getPeerCertificateChain() const {      std::vector<Certificate::ref> result;      STACK_OF(X509)* chain = SSL_get_peer_cert_chain(handle_.get()); diff --git a/Swiften/TLS/OpenSSL/OpenSSLContext.h b/Swiften/TLS/OpenSSL/OpenSSLContext.h index bf897a7..cfa852a 100644 --- a/Swiften/TLS/OpenSSL/OpenSSLContext.h +++ b/Swiften/TLS/OpenSSL/OpenSSLContext.h @@ -49,6 +49,7 @@ namespace Swift {              bool setPrivateKey(const PrivateKey::ref& privateKey) override final;              bool setClientCertificate(CertificateWithKey::ref cert) override final;              void setAbortTLSHandshake(bool abort) override final; +            bool setDiffieHellmanParameters(const ByteArray& parametersInOpenSslDer) override final;              void handleDataFromNetwork(const SafeByteArray&) override final;              void handleDataFromApplication(const SafeByteArray&) override final; diff --git a/Swiften/TLS/OpenSSL/OpenSSLContextFactory.cpp b/Swiften/TLS/OpenSSL/OpenSSLContextFactory.cpp index af0966e..9d0ad72 100644 --- a/Swiften/TLS/OpenSSL/OpenSSLContextFactory.cpp +++ b/Swiften/TLS/OpenSSL/OpenSSLContextFactory.cpp @@ -6,9 +6,15 @@  #include <Swiften/TLS/OpenSSL/OpenSSLContextFactory.h> +#include <openssl/bio.h> +#include <openssl/dh.h> +#include <openssl/pem.h> +  #include <Swiften/Base/Log.h>  #include <Swiften/TLS/OpenSSL/OpenSSLContext.h> +#pragma clang diagnostic ignored "-Wshorten-64-to-32" +  namespace Swift {  bool OpenSSLContextFactory::canCreate() const { @@ -19,6 +25,26 @@ TLSContext* OpenSSLContextFactory::createTLSContext(const TLSOptions&, TLSContex      return new OpenSSLContext(mode);  } +ByteArray OpenSSLContextFactory::convertDHParametersFromPEMToDER(const std::string& dhParametersInPEM) { +    ByteArray dhParametersInDER; + +    auto bio = std::unique_ptr<BIO, decltype(&BIO_free)>(BIO_new(BIO_s_mem()), BIO_free); +    if (bio) { +        BIO_write(bio.get(), dhParametersInPEM.data(), dhParametersInPEM.size()); +        if (auto params = PEM_read_bio_DHparams(bio.get(), nullptr, nullptr, nullptr)) { +            unsigned char* buffer = nullptr; +            auto len = i2d_DHparams(params, &buffer); +            if (len > 0) { +                dhParametersInDER = createByteArray(buffer, static_cast<size_t>(len)); +                free(buffer); +            } +            DH_free(params); + +        } +    } +    return dhParametersInDER; +} +  void OpenSSLContextFactory::setCheckCertificateRevocation(bool check) {      if (check) {          SWIFT_LOG(warning) << "CRL Checking not supported for OpenSSL" << std::endl; diff --git a/Swiften/TLS/OpenSSL/OpenSSLContextFactory.h b/Swiften/TLS/OpenSSL/OpenSSLContextFactory.h index 63fc17e..db7fa34 100644 --- a/Swiften/TLS/OpenSSL/OpenSSLContextFactory.h +++ b/Swiften/TLS/OpenSSL/OpenSSLContextFactory.h @@ -14,6 +14,8 @@ namespace Swift {              bool canCreate() const override final;              virtual TLSContext* createTLSContext(const TLSOptions& tlsOptions, TLSContext::Mode mode) override final; +            virtual ByteArray convertDHParametersFromPEMToDER(const std::string& dhParametersInPEM) override final; +              // Not supported              virtual void setCheckCertificateRevocation(bool b) override final;              virtual void setDisconnectOnCardRemoval(bool b) override final; diff --git a/Swiften/TLS/TLSContext.cpp b/Swiften/TLS/TLSContext.cpp index 8246dde..cc05834 100644 --- a/Swiften/TLS/TLSContext.cpp +++ b/Swiften/TLS/TLSContext.cpp @@ -31,6 +31,11 @@ bool TLSContext::setPrivateKey(const PrivateKey::ref& /* privateKey */) {      return false;  } +bool TLSContext::setDiffieHellmanParameters(const ByteArray& /*parametersInOpenSslDer*/) { +    assert(false); +    return false; +} +  void TLSContext::setAbortTLSHandshake(bool /* abort */) {      assert(false);  } diff --git a/Swiften/TLS/TLSContext.h b/Swiften/TLS/TLSContext.h index 653e8d2..55a86cd 100644 --- a/Swiften/TLS/TLSContext.h +++ b/Swiften/TLS/TLSContext.h @@ -32,6 +32,7 @@ namespace Swift {              virtual bool setPrivateKey(const PrivateKey::ref& /* privateKey */);              virtual bool setClientCertificate(CertificateWithKey::ref cert) = 0; +            virtual bool setDiffieHellmanParameters(const ByteArray& parametersInOpenSslDer);              /**               *  This method can be used during the \ref onServerNameRequested signal, diff --git a/Swiften/TLS/TLSContextFactory.cpp b/Swiften/TLS/TLSContextFactory.cpp index d196e15..91e60d6 100644 --- a/Swiften/TLS/TLSContextFactory.cpp +++ b/Swiften/TLS/TLSContextFactory.cpp @@ -6,9 +6,16 @@  #include <Swiften/TLS/TLSContextFactory.h> +#include <cassert> +  namespace Swift {  TLSContextFactory::~TLSContextFactory() {  } +ByteArray TLSContextFactory::convertDHParametersFromPEMToDER(const std::string& /* pem */) { +    assert(false); +    return ByteArray(); +} +  } diff --git a/Swiften/TLS/TLSContextFactory.h b/Swiften/TLS/TLSContextFactory.h index ca9d98b..9da3392 100644 --- a/Swiften/TLS/TLSContextFactory.h +++ b/Swiften/TLS/TLSContextFactory.h @@ -7,6 +7,7 @@  #pragma once  #include <Swiften/Base/API.h> +#include <Swiften/Base/ByteArray.h>  #include <Swiften/TLS/TLSContext.h>  #include <Swiften/TLS/TLSOptions.h> @@ -20,5 +21,7 @@ namespace Swift {              virtual TLSContext* createTLSContext(const TLSOptions& tlsOptions, TLSContext::Mode = TLSContext::Mode::Client) = 0;              virtual void setCheckCertificateRevocation(bool b) = 0;              virtual void setDisconnectOnCardRemoval(bool b) = 0; + +            virtual ByteArray convertDHParametersFromPEMToDER(const std::string& pem);      };  } diff --git a/Swiften/TLS/UnitTest/ClientServerTest.cpp b/Swiften/TLS/UnitTest/ClientServerTest.cpp index 5777856..e60364e 100644 --- a/Swiften/TLS/UnitTest/ClientServerTest.cpp +++ b/Swiften/TLS/UnitTest/ClientServerTest.cpp @@ -250,6 +250,22 @@ X137HnkpmtJGF+bcMRwY5u9fSQQZtBNLCadRsvHnz6J+1uodFDnre0+Q4dokmFfv  -----END RSA PRIVATE KEY-----  )"; +auto dhParamsOpenSslDer1024 = R"(-----BEGIN DH PARAMETERS----- +MIGHAoGBANjw4f5+gu8b8X8O6ALyJA1tH9TQTWZEI3YjUKQ1m0dVBMJ6XDC7FLJn +gqE4hIGcm1FAWwIiuo0uMufqyVwFT2c+G8j4JHWK5z1tEP+GaqiO34N0cUo86qHp +THSkJN7LuHbYRqI9fHWDZocW/5yAsDq5RPUCjFZAoh1BWdfDFfrjAgEC +-----END DH PARAMETERS----- +)"; +auto dhParamsOpenSslDer2048 = R"(-----BEGIN DH PARAMETERS----- +MIIBCAKCAQEA0Q6vD5qtrh3XEkVkbN29ord/k3sgo2Q3PiFmyFt89qqVbebEzYmt +t8DwaFGMcGlyKs4Lb1s7vocm9y3M9C0FZm85Muvv8WCbLZVZ+wfEtMibOjgRoDqt +p7Qqe7/iPgMVrSjWegVkg3V8K8dnPpohPClM0yOe4NpBjSVNgBVJRpEtH8gFiCor +H7hw63HpN/MgFdkjZNeCN+erv8p673xH8LrN98gQpkdQ9vCqYt1dHxF2XZcxBp8x +XganwPeGgQosofkA6nVB70hyjwjEyxnHJZIMlx6DPXWC7X6ed0SazgH0sQNdACvG +uU1zHCVIv6/f0adKrJg0s1jrM3qWZ6HmUwIBAg== +-----END DH PARAMETERS----- +)"; +  auto createTLSContext = [](TLSContext::Mode mode) {      auto tlsFactories = std::make_shared<PlatformTLSFactories>(); @@ -678,3 +694,67 @@ TEST(ClientServerTest, testClientServerEqualFinishedMessage) {      ASSERT_EQ(serverContext->getPeerFinishMessage(), clientContext->getFinishMessage());      ASSERT_EQ(clientContext->getPeerFinishMessage(), serverContext->getFinishMessage());  } + +TEST(ClientServerTest, testClientServerBasicCommunicationWith2048BitDHParams) { +    auto clientContext = createTLSContext(TLSContext::Mode::Client); +    auto serverContext = createTLSContext(TLSContext::Mode::Server); + +    TLSClientServerEventHistory events(clientContext.get(), serverContext.get()); + +    ClientServerConnector connector(clientContext.get(), serverContext.get()); + +    auto tlsFactories = std::make_shared<PlatformTLSFactories>(); + +    ASSERT_EQ(true, serverContext->setCertificateChain(tlsFactories->getCertificateFactory()->createCertificateChain(createByteArray(certificatePEM["capulet.example"])))); + +    auto privateKey = tlsFactories->getCertificateFactory()->createPrivateKey(createSafeByteArray(privateKeyPEM["capulet.example"])); +    ASSERT_NE(nullptr, privateKey.get()); +    ASSERT_EQ(true, serverContext->setPrivateKey(privateKey)); + +    ASSERT_EQ(true, serverContext->setDiffieHellmanParameters(tlsFactories->getTLSContextFactory()->convertDHParametersFromPEMToDER(dhParamsOpenSslDer2048))); + +    serverContext->accept(); +    clientContext->connect(); + +    clientContext->handleDataFromApplication(createSafeByteArray("This is a test message from the client.")); +    serverContext->handleDataFromApplication(createSafeByteArray("This is a test message from the server.")); + +    ASSERT_EQ(safeByteArrayToString(createSafeByteArray("This is a test message from the client.")), safeByteArrayToString(boost::apply_visitor(TLSEventToSafeByteArrayVisitor(), std::find_if(events.events.begin(), events.events.end(), [](std::pair<std::string, TLSEvent>& event){ +        return event.first == "server" && (event.second.type() == typeid(TLSDataForApplication)); +    })->second))); +    ASSERT_EQ(safeByteArrayToString(createSafeByteArray("This is a test message from the server.")), safeByteArrayToString(boost::apply_visitor(TLSEventToSafeByteArrayVisitor(), std::find_if(events.events.begin(), events.events.end(), [](std::pair<std::string, TLSEvent>& event){ +        return event.first == "client" && (event.second.type() == typeid(TLSDataForApplication)); +    })->second))); +} + +TEST(ClientServerTest, testClientServerBasicCommunicationWith1024BitDHParams) { +    auto clientContext = createTLSContext(TLSContext::Mode::Client); +    auto serverContext = createTLSContext(TLSContext::Mode::Server); + +    TLSClientServerEventHistory events(clientContext.get(), serverContext.get()); + +    ClientServerConnector connector(clientContext.get(), serverContext.get()); + +    auto tlsFactories = std::make_shared<PlatformTLSFactories>(); + +    ASSERT_EQ(true, serverContext->setCertificateChain(tlsFactories->getCertificateFactory()->createCertificateChain(createByteArray(certificatePEM["capulet.example"])))); + +    auto privateKey = tlsFactories->getCertificateFactory()->createPrivateKey(createSafeByteArray(privateKeyPEM["capulet.example"])); +    ASSERT_NE(nullptr, privateKey.get()); +    ASSERT_EQ(true, serverContext->setPrivateKey(privateKey)); + +    ASSERT_EQ(true, serverContext->setDiffieHellmanParameters(tlsFactories->getTLSContextFactory()->convertDHParametersFromPEMToDER(dhParamsOpenSslDer1024))); + +    serverContext->accept(); +    clientContext->connect(); + +    clientContext->handleDataFromApplication(createSafeByteArray("This is a test message from the client.")); +    serverContext->handleDataFromApplication(createSafeByteArray("This is a test message from the server.")); + +    ASSERT_EQ(safeByteArrayToString(createSafeByteArray("This is a test message from the client.")), safeByteArrayToString(boost::apply_visitor(TLSEventToSafeByteArrayVisitor(), std::find_if(events.events.begin(), events.events.end(), [](std::pair<std::string, TLSEvent>& event){ +        return event.first == "server" && (event.second.type() == typeid(TLSDataForApplication)); +    })->second))); +    ASSERT_EQ(safeByteArrayToString(createSafeByteArray("This is a test message from the server.")), safeByteArrayToString(boost::apply_visitor(TLSEventToSafeByteArrayVisitor(), std::find_if(events.events.begin(), events.events.end(), [](std::pair<std::string, TLSEvent>& event){ +        return event.first == "client" && (event.second.type() == typeid(TLSDataForApplication)); +    })->second))); +} | 
 Swift
 Swift