From 68dd665d51c925a118cfced4583942b7157b59de Mon Sep 17 00:00:00 2001
From: Edwin Mons <edwin.mons@isode.com>
Date: Fri, 18 Jan 2019 16:25:58 +0100
Subject: Allow ownership transfer of certificates

OpenSSL TLS contexts assume ownership of any additional certificate
passed into it.  The CertificateFactory now returns a vector of
unique_ptrs, and OpenSSLContext will do the needful with releasing
ownership at the right moment.

A unit test has been added that uses a chained certificate in
client/server context. Before the fix, this test would either fail, or
result in a segmentation fault, depending on the mood of OpenSSL.

Test-Information:

Unit tests pass on Debian 9
Ran manual tests with server test code, tested both chained and single
certificates, and no longer observed crashes when accepting a
connection.

Change-Id: I21814969e45c7d77e9a1af14f2c958c4c0311cd0

diff --git a/Swiften/TLS/CertificateFactory.cpp b/Swiften/TLS/CertificateFactory.cpp
index 303bcf7..aaf27d9 100644
--- a/Swiften/TLS/CertificateFactory.cpp
+++ b/Swiften/TLS/CertificateFactory.cpp
@@ -23,9 +23,9 @@ namespace Swift {
 CertificateFactory::~CertificateFactory() {
 }
 
-std::vector<Certificate::ref> CertificateFactory::createCertificateChain(const ByteArray& /* data */) {
+std::vector<std::unique_ptr<Certificate>> CertificateFactory::createCertificateChain(const ByteArray& /* data */) {
     assert(false);
-    return std::vector<Certificate::ref>();
+    return std::vector<std::unique_ptr<Certificate>>();
 }
 
 PrivateKey::ref CertificateFactory::createPrivateKey(const SafeByteArray& data, boost::optional<SafeByteArray> password) {
diff --git a/Swiften/TLS/CertificateFactory.h b/Swiften/TLS/CertificateFactory.h
index cb7fb6e..619031c 100644
--- a/Swiften/TLS/CertificateFactory.h
+++ b/Swiften/TLS/CertificateFactory.h
@@ -19,7 +19,7 @@ namespace Swift {
             virtual ~CertificateFactory();
 
             virtual Certificate* createCertificateFromDER(const ByteArray& der) = 0;
-            virtual std::vector<Certificate::ref> createCertificateChain(const ByteArray& data);
+            virtual std::vector<std::unique_ptr<Certificate>> createCertificateChain(const ByteArray& data);
             PrivateKey::ref createPrivateKey(const SafeByteArray& data, boost::optional<SafeByteArray> password = boost::optional<SafeByteArray>());
     };
 }
diff --git a/Swiften/TLS/OpenSSL/OpenSSLCertificateFactory.cpp b/Swiften/TLS/OpenSSL/OpenSSLCertificateFactory.cpp
index c94702c..5eb626b 100644
--- a/Swiften/TLS/OpenSSL/OpenSSLCertificateFactory.cpp
+++ b/Swiften/TLS/OpenSSL/OpenSSLCertificateFactory.cpp
@@ -20,8 +20,8 @@ Certificate* OpenSSLCertificateFactory::createCertificateFromDER(const ByteArray
     return new OpenSSLCertificate(der);
 }
 
-std::vector<Certificate::ref> OpenSSLCertificateFactory::createCertificateChain(const ByteArray& data) {
-    std::vector<Certificate::ref> certificateChain;
+std::vector<std::unique_ptr<Certificate>> OpenSSLCertificateFactory::createCertificateChain(const ByteArray& data) {
+    std::vector<std::unique_ptr<Certificate>> certificateChain;
 
     if (data.size() > std::numeric_limits<int>::max()) {
         return certificateChain;
@@ -35,11 +35,11 @@ std::vector<Certificate::ref> OpenSSLCertificateFactory::createCertificateChain(
     auto x509certFromPEM = PEM_read_bio_X509(bio.get(), &openSSLCert, nullptr, nullptr);
     if (x509certFromPEM && openSSLCert) {
         std::shared_ptr<X509> x509Cert(openSSLCert, X509_free);
-        certificateChain.push_back(std::make_shared<OpenSSLCertificate>(x509Cert));
+        certificateChain.emplace_back(std::make_unique<OpenSSLCertificate>(x509Cert));
         openSSLCert = nullptr;
         while ((x509certFromPEM = PEM_read_bio_X509(bio.get(), &openSSLCert, nullptr, nullptr)) != nullptr) {
             std::shared_ptr<X509> x509Cert(openSSLCert, X509_free);
-            certificateChain.push_back(std::make_shared<OpenSSLCertificate>(x509Cert));
+            certificateChain.emplace_back(std::make_unique<OpenSSLCertificate>(x509Cert));
             openSSLCert = nullptr;
         }
     }
diff --git a/Swiften/TLS/OpenSSL/OpenSSLCertificateFactory.h b/Swiften/TLS/OpenSSL/OpenSSLCertificateFactory.h
index af45a33..48e9b2c 100644
--- a/Swiften/TLS/OpenSSL/OpenSSLCertificateFactory.h
+++ b/Swiften/TLS/OpenSSL/OpenSSLCertificateFactory.h
@@ -16,6 +16,6 @@ namespace Swift {
             virtual ~OpenSSLCertificateFactory() override final;
 
             virtual Certificate* createCertificateFromDER(const ByteArray& der) override final;
-            virtual std::vector<Certificate::ref> createCertificateChain(const ByteArray& data) override final;
+            virtual std::vector<std::unique_ptr<Certificate>> createCertificateChain(const ByteArray& data) override final;
     };
 }
diff --git a/Swiften/TLS/OpenSSL/OpenSSLContext.cpp b/Swiften/TLS/OpenSSL/OpenSSLContext.cpp
index 968ef8f..e9889bc 100644
--- a/Swiften/TLS/OpenSSL/OpenSSLContext.cpp
+++ b/Swiften/TLS/OpenSSL/OpenSSLContext.cpp
@@ -338,14 +338,14 @@ void OpenSSLContext::sendPendingDataToApplication() {
     }
 }
 
-bool OpenSSLContext::setCertificateChain(const std::vector<Certificate::ref>& certificateChain) {
+bool OpenSSLContext::setCertificateChain(std::vector<std::unique_ptr<Certificate>>&& certificateChain) {
     if (certificateChain.size() == 0) {
         SWIFT_LOG(warning) << "Trying to load empty certificate chain." << std::endl;
         return false;
     }
 
     // load endpoint certificate
-    auto openSSLCert = std::dynamic_pointer_cast<OpenSSLCertificate>(certificateChain[0]);
+    auto openSSLCert = dynamic_cast<OpenSSLCertificate*>(certificateChain[0].get());
     if (!openSSLCert) {
         return false;
     }
@@ -355,8 +355,8 @@ bool OpenSSLContext::setCertificateChain(const std::vector<Certificate::ref>& ce
     }
 
     if (certificateChain.size() > 1) {
-        for (auto certificate : range(certificateChain.begin() + 1, certificateChain.end())) {
-            auto openSSLCert = std::dynamic_pointer_cast<OpenSSLCertificate>(certificate);
+        for (auto certificate = certificateChain.begin() + 1; certificate != certificateChain.end(); ++certificate) {
+            auto openSSLCert = dynamic_cast<OpenSSLCertificate*>(certificate->get());
             if (!openSSLCert) {
                 return false;
             }
@@ -364,6 +364,7 @@ bool OpenSSLContext::setCertificateChain(const std::vector<Certificate::ref>& ce
                 SWIFT_LOG(warning) << "Trying to load empty certificate chain." << std::endl;
                 return false;
             }
+            certificate->release();
         }
     }
 
diff --git a/Swiften/TLS/OpenSSL/OpenSSLContext.h b/Swiften/TLS/OpenSSL/OpenSSLContext.h
index cfa852a..c18a6f4 100644
--- a/Swiften/TLS/OpenSSL/OpenSSLContext.h
+++ b/Swiften/TLS/OpenSSL/OpenSSLContext.h
@@ -45,7 +45,7 @@ namespace Swift {
             void connect() override final;
             void connect(const std::string& requestHostname) override final;
 
-            bool setCertificateChain(const std::vector<Certificate::ref>& certificateChain) override final;
+            bool setCertificateChain(std::vector<std::unique_ptr<Certificate>>&& certificateChain) override final;
             bool setPrivateKey(const PrivateKey::ref& privateKey) override final;
             bool setClientCertificate(CertificateWithKey::ref cert) override final;
             void setAbortTLSHandshake(bool abort) override final;
diff --git a/Swiften/TLS/TLSContext.cpp b/Swiften/TLS/TLSContext.cpp
index cc05834..666ea7f 100644
--- a/Swiften/TLS/TLSContext.cpp
+++ b/Swiften/TLS/TLSContext.cpp
@@ -21,7 +21,7 @@ void TLSContext::connect(const std::string& /* serverName */) {
     assert(false);
 }
 
-bool TLSContext::setCertificateChain(const std::vector<Certificate::ref>& /* certificateChain */) {
+bool TLSContext::setCertificateChain(std::vector<std::unique_ptr<Certificate>>&& /* certificateChain */) {
     assert(false);
     return false;
 }
diff --git a/Swiften/TLS/TLSContext.h b/Swiften/TLS/TLSContext.h
index 9b0a2eb..003069f 100644
--- a/Swiften/TLS/TLSContext.h
+++ b/Swiften/TLS/TLSContext.h
@@ -28,7 +28,7 @@ namespace Swift {
             virtual void connect() = 0;
             virtual void connect(const std::string& serverName);
 
-            virtual bool setCertificateChain(const std::vector<Certificate::ref>& /* certificateChain */);
+            virtual bool setCertificateChain(std::vector<std::unique_ptr<Certificate>>&& /* certificateChain */);
             virtual bool setPrivateKey(const PrivateKey::ref& /* privateKey */);
 
             virtual bool setClientCertificate(CertificateWithKey::ref cert) = 0;
diff --git a/Swiften/TLS/UnitTest/CertificateTest.cpp b/Swiften/TLS/UnitTest/CertificateTest.cpp
index aac2cfb..d5bf210 100644
--- a/Swiften/TLS/UnitTest/CertificateTest.cpp
+++ b/Swiften/TLS/UnitTest/CertificateTest.cpp
@@ -73,7 +73,7 @@ zqCzpwGL
             auto certificateChain = tlsFactories.getCertificateFactory()->createCertificateChain(createByteArray(PEMCertificate));
             CPPUNIT_ASSERT_EQUAL(size_t(1), certificateChain.size());
 
-            auto certificate = certificateChain[0];
+            auto certificate = certificateChain[0].get();
             CPPUNIT_ASSERT_EQUAL(std::string("/CN=montague.example"), certificate->getSubjectName());
         }
 
diff --git a/Swiften/TLS/UnitTest/ClientServerTest.cpp b/Swiften/TLS/UnitTest/ClientServerTest.cpp
index e60364e..24bd7c5 100644
--- a/Swiften/TLS/UnitTest/ClientServerTest.cpp
+++ b/Swiften/TLS/UnitTest/ClientServerTest.cpp
@@ -84,7 +84,49 @@ S05kF7XRpludRB4QkAJt5BNNv6BPP7HPIKyR/rq94ONvzVPAo7uASyFE2sMBsfwP
 pXAI1LVolPCoUC13jEkKdmc8kMSxU+XtsvFryNhkfQtZfSg+nBRFYptFE7GrZ9WY
 GMSL4g==
 -----END CERTIFICATE-----
-)"}};
+)"},
+    {"casigned.example.com",
+R"(-----BEGIN CERTIFICATE-----
+MIIDYTCCAkmgAwIBAgIJAPEpYlUWlJW8MA0GCSqGSIb3DQEBCwUAMEAxCzAJBgNV
+BAYTAkdCMRAwDgYDVQQIDAdFbmdsYW5kMQ4wDAYDVQQKDAVJc29kZTEPMA0GA1UE
+AwwGVGVzdENBMB4XDTE4MDExODAwMDAwMFoXDTQ5MDExODAwMDAwMFowTjELMAkG
+A1UEBhMCR0IxEDAOBgNVBAgMB0VuZ2xhbmQxDjAMBgNVBAoMBUlzb2RlMR0wGwYD
+VQQDDBRjYXNpZ25lZC5leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAKw4iCscGIDCc55mwxgJsn/v2GEorpE9zHYsMfl6px2aRLGgB8ki
+xYyNiEPA/b/ilShRp7pp22LPb5O3aOVVWzAs5FTvPdFY2vS8YIxR6XSKXO3u4Q8/
+w8CR0AbKpeCtL0TwSl1u76nq6ORMep6QGsTjDLQ7wUwdShL4qV4nIGxJWon/5GI0
+nl4Xr/wzmysbMjAMSiWOR90DNZMvqQBBhQcJdqdirc+whR8gOhIMvJBn5jlMuFEB
+zL/bR+kG/zFuD0EMsMTy6TETefYuxeWmhuzQENyAV5+1v48G/1a9zzN9Y0xQ6T0N
+ppbLzq+/zhxT1eBN8/O0bAGUzzk1VSFvouECAwEAAaNQME4wHQYDVR0OBBYEFCnR
+umlxjdaUvcpf77zahrDmPnt1MB8GA1UdIwQYMBaAFAbbhPAKtD5YzxQqGH2Um4/f
+OmdFMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAEPrTTKS+7A4dJJh
+gSAS44ZYyR8/kt9Y3V4qxJM2xrOrW6rM8N15n2i/osSy0AYHiPuvgDG+D7hLt5Ct
+7jZKrp3JRsBaU8//9k6+euwVyWS+EKo/eb7qtSNibZOk7GwrXekJMbRXz1cHTKnW
+0R8UG+EMkOqKQh5dhWuEBXff9SYLTALf0/i+/Ixl3b9rQ6zpY/7UwBdlWLaliM1i
+odIgVu1XRE6Su+bGMa1L5ArniN0LMFq9Mxag2H0V7Kru7vIvbBkL7U6tbi7u26hv
+q4kUFROW2U2C02FTmJeSEBvWoDyMoVjKkmaTL0+vDSQRPGtCsvCgaCXgOwU2Po9s
+8jjHQxg=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDUzCCAjugAwIBAgIJAPEpYlUWlJW7MA0GCSqGSIb3DQEBCwUAMEAxCzAJBgNV
+BAYTAkdCMRAwDgYDVQQIDAdFbmdsYW5kMQ4wDAYDVQQKDAVJc29kZTEPMA0GA1UE
+AwwGVGVzdENBMB4XDTE4MDExODAwMDAwMFoXDTQ5MDExODAwMDAwMFowQDELMAkG
+A1UEBhMCR0IxEDAOBgNVBAgMB0VuZ2xhbmQxDjAMBgNVBAoMBUlzb2RlMQ8wDQYD
+VQQDDAZUZXN0Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCiCA+9
+bdSHFNPOgbsnhrKbLJP+1lxWTe06+ExwJA3QgCKsR13MsAK8rhmuNB0k8ZIFJL+c
+yUOUgw0370eP940QAtK+HinJpvaGEZKEwaB8VUCjzFTb7zUBio1Y7B45aawEV3qT
+Lzcnil3f7vPIxnAoaptzPriySdggIsimj+y6AWum5FUPyfZzF7EnYfF/VH8V/ZNX
+fku7PPbaeDHvu4EF/0s8P+/l6jddz8dqbDMjH3GDM8sjryWPQPNDjKZ1x80BIdyq
+s9m/kXqIIySNwdIa/X+nYTMchUa5y46n2N4n0RA4F+rf+Ni1Cxk9Ejmmz5hinV+t
+Yzh6jsbB7yZiqEnzAgMBAAGjUDBOMB0GA1UdDgQWBBQG24TwCrQ+WM8UKhh9lJuP
+3zpnRTAfBgNVHSMEGDAWgBQG24TwCrQ+WM8UKhh9lJuP3zpnRTAMBgNVHRMEBTAD
+AQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBMHQ3WMEhkEc0VoOEw3mbsngt1eyJz+nFM
+FeGdRb7JSwpJfe/yBxyGodGyHsQJPVole6sUdq8S1QGT547PkgDHc6Btoq96Mahq
+brgfx1JL9a1F8qaqcENebHc7ltW8kps4xtdlithfo4nKaciYZ5mKbug+AFv569mb
+LU3F282dyW1dLa7+L8dGbb8Ntpnp0BB0Cotm4GX3Xi6Y+fikouqcmXj7vX+uMhG4
+pQpXqb2ML1Gev4w6XUsnls+OJok97x99NsOcqtwqsLJS/sg0cpwrgZ9+50hQKlHO
+8H6hhNjGBkvpIiNsWb9UOc+Id86J+drs9Ed93Eyyvwnq2XcqPGF3
+-----END CERTIFICATE-----)"}};
 std::map<std::string, std::string> privateKeyPEM = {
     {"montague.example",
 R"(-----BEGIN PRIVATE KEY-----
@@ -192,6 +234,36 @@ mgPPV65cznhofUsg2QenT8zKisvYPYN3p3p9Jo6IqHyT/CCymwIB4OMZITiwXxQs
 PMAxlZGkX3Uri5A8Ln3QQ46elanI2TlC+ZDa84gu/Gw691JWCfsaSaQDTJKnGqos
 dwiNVl130YWaJLjiA9Poc2llKtypfQ8=
 -----END PRIVATE KEY-----
+)"},
+    {"casigned.example.com",
+R"(-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCsOIgrHBiAwnOe
+ZsMYCbJ/79hhKK6RPcx2LDH5eqcdmkSxoAfJIsWMjYhDwP2/4pUoUae6adtiz2+T
+t2jlVVswLORU7z3RWNr0vGCMUel0ilzt7uEPP8PAkdAGyqXgrS9E8Epdbu+p6ujk
+THqekBrE4wy0O8FMHUoS+KleJyBsSVqJ/+RiNJ5eF6/8M5srGzIwDEoljkfdAzWT
+L6kAQYUHCXanYq3PsIUfIDoSDLyQZ+Y5TLhRAcy/20fpBv8xbg9BDLDE8ukxE3n2
+LsXlpobs0BDcgFeftb+PBv9Wvc8zfWNMUOk9DaaWy86vv84cU9XgTfPztGwBlM85
+NVUhb6LhAgMBAAECggEAP5KesUstwFoHU/GbEsSBn7hpp3Pc/MBTOUwXJoCgL81C
+jk8EkLrFMZ0NL/WNtcduR/PcdnOdCFyKU3zgu8dGYgIwRyoJJ74lFTJ0cVfLVbm9
+lBcZ/QcMu4kXwWoM0WMcj9YjnVnWHmMYlS2mFeIb/5HQnrdwIyisr1QbMSZAUbgn
+HOLSjkd0KUcXxwP9HfE/8zUFbUsv/wPHE9T5eWqZz7lKZRvgUyk3jYElpewxqPvR
+HPOq9BN87ft7rPzmmZ4JCU2tM5MEQONo3jT5pljTU/iz4pfs1HArHS+/zZbGcoiu
+AhODErhLucodwZ07MZsE9KAdGPGUeob4SgMwmkIiAQKBgQDYZ33DHOgYd5Fa7Tqv
+TC77Nbpjmnk5lyoInNf+7pxBTgqIuKbpS6Ctq76nHI0qerNfd44LqojQEJ9S5rbL
+3s+HR+pypx3DyysE92uLaVsF4rfwZeEpJyQ1Q9NGbsKVb2nNrdGs3LZhG5PL+JQT
+8lS9h/sMIbh5Gd/Dkt8a2HlTawKBgQDLu3YdXWeWUOcq63YrLFDO+RUGsCe1cf+2
+3wTmMRgxfzpAPDZKymUPwrJNd1ddCQiRVKg91pLhlDl8B89Q4iWdOpYnE6vrnw3w
+6iEdEyA6IauvEvD3JPXHGtVHKBS/wz06wQVGzsgMvVun1w32SDzTGZ/somvkN1UE
+BTMRVqXB4wKBgCgkgnq4GQG45FjGmtU7v5dP7yRc2lHpjZ2NYq/imU+v51pXTncG
+VWcB7drX/AO+QRnbdpkJaFmYS8W4EH6e9UY1+/KKt4XDYVaJgwSYZY8g8FgCvhLB
+NQFAdKejEitgQHMr5DI5uwcmc3MpyGYu1LNXzyT/+FVWjGCeFQ7IyzDDAoGAXK9I
++ez/bkQaFs2OMe/0R2TL6wIC3qohMpndSbf2ELaX0pdR/856EaR6p4FujlXIvw0r
+iQ5wPg3H5SRMbbikchYwL1DkusnedsadD/QeijO9PmW4mEcJRW5wrvGOFvuEhJFB
+jEgQfLM82muc33lXqpYSyn3N5cJCfBS9edrYiA8CgYEA0Tsa4KvwzmBXzy2jexUT
+PPYtV9S7hS0D7Owf5SBI1wtWczOu3Y6DsCG4mbDi/tvo1dxC9d5Ns8RXHH9mtdyn
+8VUuSu24lk7VZ0OP5/byiAGqC2urDFGe0iBqePdb+3uS1g132LzAJm4RqBYw4Xjd
+P6n9b0V3iodcFLMTy1ShJ+I=
+-----END PRIVATE KEY-----
 )"}};
 
 auto montagueEncryptedPEM = R"(-----BEGIN RSA PRIVATE KEY-----
@@ -568,6 +640,40 @@ TEST(ClientServerTest, testClientServerBasicCommunicationEncryptedPrivateKeyRigh
     })->second)));
 }
 
+TEST(ClientServerTest, testClientServerBasicCommunicationWithChainedCert) {
+    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_TRUE(serverContext->setCertificateChain(tlsFactories->getCertificateFactory()->createCertificateChain(createByteArray(certificatePEM["casigned.example.com"]))));
+
+    auto privateKey = tlsFactories->getCertificateFactory()->createPrivateKey(createSafeByteArray(privateKeyPEM["casigned.example.com"]));
+    ASSERT_NE(nullptr, privateKey.get());
+    ASSERT_TRUE(serverContext->setPrivateKey(privateKey));
+
+    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."));
+
+    auto serverEvent = std::find_if(events.events.begin(), events.events.end(), [](std::pair<std::string, TLSEvent>& event){
+        return event.first == "server" && (event.second.type() == typeid(TLSDataForApplication));
+    });
+    ASSERT_NE(events.events.end(), serverEvent);
+    ASSERT_EQ(safeByteArrayToString(createSafeByteArray("This is a test message from the client.")), safeByteArrayToString(boost::apply_visitor(TLSEventToSafeByteArrayVisitor(), serverEvent->second)));
+    auto clientEvent = std::find_if(events.events.begin(), events.events.end(), [](std::pair<std::string, TLSEvent>& event){
+        return event.first == "client" && (event.second.type() == typeid(TLSDataForApplication));
+    });
+    ASSERT_NE(events.events.end(), clientEvent);
+    ASSERT_EQ(safeByteArrayToString(createSafeByteArray("This is a test message from the server.")), safeByteArrayToString(boost::apply_visitor(TLSEventToSafeByteArrayVisitor(), clientEvent->second)));
+}
+
 TEST(ClientServerTest, testSettingPrivateKeyWithWrongPassword) {
     auto clientContext = createTLSContext(TLSContext::Mode::Client);
     auto serverContext = createTLSContext(TLSContext::Mode::Server);
@@ -610,7 +716,7 @@ TEST(ClientServerTest, testClientServerSNIRequestedHostAvailable) {
     serverContext->onServerNameRequested.connect([&](const std::string& requestedName) {
         if (certificatePEM.find(requestedName) != certificatePEM.end() && privateKeyPEM.find(requestedName) != privateKeyPEM.end()) {
             auto certChain = tlsFactories->getCertificateFactory()->createCertificateChain(createByteArray(certificatePEM[requestedName]));
-            ASSERT_EQ(true, serverContext->setCertificateChain(certChain));
+            ASSERT_EQ(true, serverContext->setCertificateChain(std::move(certChain)));
 
             auto privateKey = tlsFactories->getCertificateFactory()->createPrivateKey(createSafeByteArray(privateKeyPEM[requestedName]));
             ASSERT_NE(nullptr, privateKey.get());
-- 
cgit v0.10.2-6-g49f6