summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Markmann <tm@ayena.de>2018-03-09 15:40:22 (GMT)
committerTobias Markmann <tm@ayena.de>2018-03-12 09:43:10 (GMT)
commit863c72980c9c25c81ef8864b310e1fd9cb9a57df (patch)
treecaf4a4cdd801f4a8d39062757f6985292884a376
parentff600776577ce4e3bbf9aa66f5980bc9cf1042a0 (diff)
downloadswift-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.cpp28
-rw-r--r--Swiften/TLS/OpenSSL/OpenSSLContext.h1
-rw-r--r--Swiften/TLS/OpenSSL/OpenSSLContextFactory.cpp26
-rw-r--r--Swiften/TLS/OpenSSL/OpenSSLContextFactory.h2
-rw-r--r--Swiften/TLS/TLSContext.cpp5
-rw-r--r--Swiften/TLS/TLSContext.h1
-rw-r--r--Swiften/TLS/TLSContextFactory.cpp7
-rw-r--r--Swiften/TLS/TLSContextFactory.h3
-rw-r--r--Swiften/TLS/UnitTest/ClientServerTest.cpp80
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)));
+}