diff options
-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 @@ -1,46 +1,48 @@ /* * Copyright (c) 2010-2018 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include <Swiften/Base/Platform.h> #ifdef SWIFTEN_PLATFORM_WINDOWS #include <windows.h> #include <wincrypt.h> #endif #include <cassert> #include <memory> #include <vector> + +#include <openssl/bio.h> #include <openssl/err.h> #include <openssl/pkcs12.h> #if defined(SWIFTEN_PLATFORM_MACOSX) #include <Security/Security.h> #endif #include <Swiften/Base/Log.h> #include <Swiften/Base/Algorithm.h> #include <Swiften/TLS/OpenSSL/OpenSSLContext.h> #include <Swiften/TLS/OpenSSL/OpenSSLCertificate.h> #include <Swiften/TLS/CertificateWithKey.h> #include <Swiften/TLS/PKCS12Certificate.h> #pragma GCC diagnostic ignored "-Wold-style-cast" #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #pragma clang diagnostic ignored "-Wshorten-64-to-32" #pragma clang diagnostic ignored "-Wcast-align" #pragma clang diagnostic ignored "-Wsign-conversion" namespace Swift { static const int MAX_FINISHED_SIZE = 4096; static const int SSL_READ_BUFFERSIZE = 8192; static void freeX509Stack(STACK_OF(X509)* stack) { sk_X509_free(stack); } namespace { @@ -66,60 +68,67 @@ namespace { std::unique_ptr<SSL_CTX> createSSL_CTX(OpenSSLContext::Mode mode) { std::unique_ptr<SSL_CTX> sslCtx; switch (mode) { case OpenSSLContext::Mode::Client: sslCtx = std::unique_ptr<SSL_CTX>(SSL_CTX_new(SSLv23_client_method())); break; case OpenSSLContext::Mode::Server: sslCtx = std::unique_ptr<SSL_CTX>(SSL_CTX_new(SSLv23_server_method())); break; } return sslCtx; } std::string openSSLInternalErrorToString() { auto bio = std::shared_ptr<BIO>(BIO_new(BIO_s_mem()), BIO_free); ERR_print_errors(bio.get()); std::string errorString; errorString.resize(BIO_pending(bio.get())); BIO_read(bio.get(), (void*)errorString.data(), errorString.size()); return errorString; } } OpenSSLContext::OpenSSLContext(Mode mode) : mode_(mode), state_(State::Start) { ensureLibraryInitialized(); context_ = createSSL_CTX(mode_); 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); } // TODO: implement CRL checking // TODO: download CRL (HTTP transport) // TODO: cache CRL downloads for configurable time period // TODO: implement OCSP support // TODO: handle OCSP stapling see https://www.rfc-editor.org/rfc/rfc4366.txt // Load system certs #if defined(SWIFTEN_PLATFORM_WINDOWS) X509_STORE* store = SSL_CTX_get_cert_store(context_.get()); HCERTSTORE systemStore = CertOpenSystemStore(0, "ROOT"); if (systemStore) { PCCERT_CONTEXT certContext = NULL; while (true) { certContext = CertFindCertificateInStore(systemStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, certContext); if (!certContext) { break; } OpenSSLCertificate cert(createByteArray(certContext->pbCertEncoded, certContext->cbCertEncoded)); if (store && cert.getInternalX509()) { X509_STORE_add_cert(store, cert.getInternalX509().get()); } } } #elif !defined(SWIFTEN_PLATFORM_MACOSX) SSL_CTX_set_default_verify_paths(context_.get()); #elif defined(SWIFTEN_PLATFORM_MACOSX) && !defined(SWIFTEN_PLATFORM_IPHONE) @@ -438,60 +447,79 @@ bool OpenSSLContext::setClientCertificate(CertificateWithKey::ref certificate) { return false; } // Parse PKCS12 X509 *certPtr = nullptr; EVP_PKEY* privateKeyPtr = nullptr; STACK_OF(X509)* caCertsPtr = nullptr; SafeByteArray password(pkcs12Certificate->getPassword()); password.push_back(0); int result = PKCS12_parse(pkcs12.get(), reinterpret_cast<const char*>(vecptr(password)), &privateKeyPtr, &certPtr, &caCertsPtr); if (result != 1) { return false; } std::shared_ptr<X509> cert(certPtr, X509_free); std::shared_ptr<EVP_PKEY> privateKey(privateKeyPtr, EVP_PKEY_free); std::shared_ptr<STACK_OF(X509)> caCerts(caCertsPtr, freeX509Stack); // Use the key & certificates if (SSL_CTX_use_certificate(context_.get(), cert.get()) != 1) { return false; } if (SSL_CTX_use_PrivateKey(context_.get(), privateKey.get()) != 1) { return false; } for (int i = 0; i < sk_X509_num(caCerts.get()); ++i) { SSL_CTX_add_extra_chain_cert(context_.get(), sk_X509_value(caCerts.get(), i)); } 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()); for (int i = 0; i < sk_X509_num(chain); ++i) { std::shared_ptr<X509> x509Cert(X509_dup(sk_X509_value(chain, i)), X509_free); Certificate::ref cert = std::make_shared<OpenSSLCertificate>(x509Cert); result.push_back(cert); } return result; } std::shared_ptr<CertificateVerificationError> OpenSSLContext::getPeerCertificateVerificationError() const { int verifyResult = SSL_get_verify_result(handle_.get()); if (verifyResult != X509_V_OK) { return std::make_shared<CertificateVerificationError>(getVerificationErrorTypeForResult(verifyResult)); } else { return std::shared_ptr<CertificateVerificationError>(); } } ByteArray OpenSSLContext::getFinishMessage() const { ByteArray data; data.resize(MAX_FINISHED_SIZE); auto size = SSL_get_finished(handle_.get(), vecptr(data), data.size()); data.resize(size); return data; } 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 @@ -22,60 +22,61 @@ namespace std { class default_delete<SSL_CTX> { public: void operator()(SSL_CTX *ptr) { SSL_CTX_free(ptr); } }; template<> class default_delete<SSL> { public: void operator()(SSL *ptr) { SSL_free(ptr); } }; } namespace Swift { class OpenSSLContext : public TLSContext, boost::noncopyable { public: OpenSSLContext(Mode mode); virtual ~OpenSSLContext() override final; void accept() override final; void connect() override final; void connect(const std::string& requestHostname) override final; bool setCertificateChain(const std::vector<Certificate::ref>& certificateChain) override final; 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; std::vector<Certificate::ref> getPeerCertificateChain() const override final; std::shared_ptr<CertificateVerificationError> getPeerCertificateVerificationError() const override final; virtual ByteArray getFinishMessage() const override final; virtual ByteArray getPeerFinishMessage() const override final; private: static void ensureLibraryInitialized(); static int handleServerNameCallback(SSL *ssl, int *ad, void *arg); static CertificateVerificationError::Type getVerificationErrorTypeForResult(int); void initAndSetBIOs(); void doAccept(); void doConnect(); void sendPendingDataToNetwork(); void sendPendingDataToApplication(); private: enum class State { Start, Accepting, Connecting, Connected, Error }; const Mode mode_; State state_; std::unique_ptr<SSL_CTX> context_; std::unique_ptr<SSL> handle_; BIO* readBIO_ = nullptr; BIO* writeBIO_ = nullptr; 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 @@ -1,37 +1,63 @@ /* * Copyright (c) 2010-2018 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #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 { return true; } TLSContext* OpenSSLContextFactory::createTLSContext(const TLSOptions&, TLSContext::Mode mode) { 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; assert(false); } } void OpenSSLContextFactory::setDisconnectOnCardRemoval(bool check) { if (check) { SWIFT_LOG(warning) << "Smart cards 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 @@ -1,21 +1,23 @@ /* * Copyright (c) 2010-2018 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once #include <Swiften/TLS/TLSContextFactory.h> namespace Swift { class OpenSSLContextFactory : public TLSContextFactory { public: 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 @@ -4,45 +4,50 @@ * See the COPYING file for more information. */ #include <Swiften/TLS/TLSContext.h> #include <cassert> namespace Swift { TLSContext::~TLSContext() { } void TLSContext::accept() { assert(false); } void TLSContext::connect(const std::string& /* serverName */) { assert(false); } bool TLSContext::setCertificateChain(const std::vector<Certificate::ref>& /* certificateChain */) { assert(false); return false; } bool TLSContext::setPrivateKey(const PrivateKey::ref& /* privateKey */) { assert(false); return false; } +bool TLSContext::setDiffieHellmanParameters(const ByteArray& /*parametersInOpenSslDer*/) { + assert(false); + return false; +} + void TLSContext::setAbortTLSHandshake(bool /* abort */) { assert(false); } Certificate::ref TLSContext::getPeerCertificate() const { std::vector<Certificate::ref> chain = getPeerCertificateChain(); return chain.empty() ? Certificate::ref() : chain[0]; } ByteArray TLSContext::getPeerFinishMessage() const { assert(false); return ByteArray(); } } 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 @@ -5,60 +5,61 @@ */ #pragma once #include <memory> #include <boost/signals2.hpp> #include <Swiften/Base/API.h> #include <Swiften/Base/SafeByteArray.h> #include <Swiften/TLS/Certificate.h> #include <Swiften/TLS/CertificateVerificationError.h> #include <Swiften/TLS/CertificateWithKey.h> #include <Swiften/TLS/PrivateKey.h> #include <Swiften/TLS/TLSError.h> namespace Swift { class SWIFTEN_API TLSContext { public: virtual ~TLSContext(); virtual void accept(); virtual void connect() = 0; virtual void connect(const std::string& serverName); virtual bool setCertificateChain(const std::vector<Certificate::ref>& /* certificateChain */); 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, * to report an error about an unknown host back to the requesting client. */ virtual void setAbortTLSHandshake(bool /* abort */); virtual void handleDataFromNetwork(const SafeByteArray&) = 0; virtual void handleDataFromApplication(const SafeByteArray&) = 0; Certificate::ref getPeerCertificate() const; virtual std::vector<Certificate::ref> getPeerCertificateChain() const = 0; virtual CertificateVerificationError::ref getPeerCertificateVerificationError() const = 0; virtual ByteArray getFinishMessage() const = 0; virtual ByteArray getPeerFinishMessage() const; public: enum class Mode { Client, Server }; public: boost::signals2::signal<void (const SafeByteArray&)> onDataForNetwork; boost::signals2::signal<void (const SafeByteArray&)> onDataForApplication; boost::signals2::signal<void (std::shared_ptr<TLSError>)> onError; boost::signals2::signal<void ()> onConnected; boost::signals2::signal<void (const std::string&)> onServerNameRequested; 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 @@ -1,14 +1,21 @@ /* * Copyright (c) 2010 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #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 @@ -1,24 +1,27 @@ /* * Copyright (c) 2010-2018 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once #include <Swiften/Base/API.h> +#include <Swiften/Base/ByteArray.h> #include <Swiften/TLS/TLSContext.h> #include <Swiften/TLS/TLSOptions.h> namespace Swift { class SWIFTEN_API TLSContextFactory { public: virtual ~TLSContextFactory(); virtual bool canCreate() const = 0; 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 @@ -223,60 +223,76 @@ yFbhUt5ZKqAvb+rt3dJswkZ1sxAbmTw290NAV4NPP8cjXUjLwmU+KNZ2VFkxt77p B/KCQc8wUjyn+yejBicfMzHVaOphwlajrt+vSNF4G7J+Wo5luTEXpWQrKq22xnah sal7IusjSgPdFpLCuyAy6atb/4aQoeXlE/r8tXbmrl48SnadwAndoZVt3gzIv1/Z oDc5koTBQk6aIoWHb6qslRt9tmrnF22aP+/a10oahgIliWAL3jUwLqZYzdbMKkMv NEbobf7kO5LTzv+w09K0A8miF+8js351FBw05gsaUHgufF3OCGAdQfXDN7d6Lxho HbhiuzxlHOnth3TWNfqhvNkwFP3gfAIaqlU1Z28AP6pZtUw93QYNABUez8QFZj5c sdUpopUO8krnwUPNup6yTB/m72Vx2aSqXgu4upxUNVJlgDFmnCBhOe0KKjzduIvy bRHxL93UZxDnpn8DBB1bgmdSzgInc2gfq91j1AyL+nbZv+kob/jG3OxMWNjenVDj +TeyP3OypAUK/8jP98ExS75mE661mN28kKrUfTRxZGt8CJY4AFL4lAzIf2p4JMch aPE30/DmXmKng+VP+3ik5FEomMLIc6QkrEzzcMYQkDsNdjd202CAXRSAqnT+VFtR MlopkSVvEpn83HdCqcANl8rNo+ANnFMyyPL7sFd470KhSVTcQVSb+wR8DOiZr8Vt uR0G3+KgdEDAvZStkWTCr5eMYhm95QVclnHhsLq0AaLrOm32PqBi2C4mGyW04Mud m7lUuRkf/mLKWZZfKleefp12waahMqSXAo3shqyTNVPKOFSVA/UF0mFGon1Npo/x 6z4hd5sbG1kiPlrt9EeTgtwFhQ0lxM755QTvAB6GXcLxkGkdNdqhJzFtTRAE9P01 CiI1JYEvTHBdGcsBbw9zJikOEXCA19fAMkHqSfo5aU/qbuvDsY2QLZkgfiMnpoOx ghQzeJ95jiYE3V5WNtB/7CRthfC54moWW7w6ZgdIuCEN6JvK0zmsahv2o16kkzWA YTw1lqaNMHIhlidRwy2Q+ke0mmNTIHHtNqLGVfOE4TwSN3VIIhXNZ5E65LuBw7tQ SyFK07dfMQXixqaeo+ytXBNTFEq1MEza/PxwUojn7njbCKhO5qGavkiyNs5nk3ZE htkhtreIUj6kHzWAvylxLbRy9+4AJA3/UCnudMRtX/McjtN2jNwZKPaXWCQF85ff koOclVf4j/eYQnWT03zXjAx1DKazIk0laEfB4soXfQfgXdFyj3YKXKKD8WzCW/ag cloY4yZVa+SWnj0P23oPdptL9vOM1NK1lXAp2tvvZHPp0UmLtXVU4eNaabC79dXC 3KU9bVruCdpQki4kGk3MvsoB9OyNEZE1jxLZ+7FI0D1XKJ4qHZcwOyGqD07+Xect w2xs4stXxvogUZdQ3G6GBANFXEjDzEu5vZn9z668mCe0cQG/iNWOR5ZGmdjlmW5O 6O9ibFmk7pc975V9SVHH9rS/GZGz/PW6CJ8O0GALw5y9fczXxjvCz7dPHK5MO40m fDWCwIqK1D2LOEewMFqOOleBhHMpVfQX+Uu34UlWHGFnOm1fK+dIdT7tss5o8Gkz gCBFpmjyi8H+VtXOy5JTTIi/80pnLO8nsv27FNPVU3UZJCZjfR9LCeqZwgF1MFIe X137HnkpmtJGF+bcMRwY5u9fSQQZtBNLCadRsvHnz6J+1uodFDnre0+Q4dokmFfv 0UveWc1CDRa3qXpzW5U6NpFjYWQmiS3KA5VY5/KHE7UJxnEI1R1gEaQ6/Ogp2cmI -----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>(); auto tlsContextFactory = tlsFactories->getTLSContextFactory(); auto tlsContext = std::unique_ptr<TLSContext>(tlsContextFactory->createTLSContext({}, mode)); return tlsContext; }; // This connects a TLSContext to another TLSContext class ClientServerConnector { public: ClientServerConnector(TLSContext* client, TLSContext* server) : clientContext_(client), serverContext_(server) { connections_.push_back(clientContext_->onDataForNetwork.connect([&](const SafeByteArray& data) { serverContext_->handleDataFromNetwork(data); })); connections_.push_back(serverContext_->onDataForNetwork.connect([&](const SafeByteArray& data) { clientContext_->handleDataFromNetwork(data); })); } private: TLSContext* clientContext_; TLSContext* serverContext_; std::vector<boost::signals2::connection> connections_; }; struct TLSDataForNetwork { SafeByteArray data; }; @@ -651,30 +667,94 @@ TEST(ClientServerTest, testClientServerSNIRequestedHostUnavailable) { ASSERT_EQ("server", events.events[1].first); ASSERT_EQ("TLSFault()", boost::apply_visitor(TLSEventToStringVisitor(), events.events[1].second)); ASSERT_EQ("client", events.events[3].first); ASSERT_EQ("TLSFault()", boost::apply_visitor(TLSEventToStringVisitor(), events.events[3].second)); } TEST(ClientServerTest, testClientServerEqualFinishedMessage) { 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)); serverContext->accept(); clientContext->connect(); 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))); +} |