CybeX
CybeX

Reputation: 2406

Statically compiled Qt 5.13.1 with OpenSSL 1.1.1d producing QSslSocket::connectToHostEncrypted: TLS initialization failed

What am I trying to achieve?

I need to create a portable (all-in-one) application, with SSL support.

What is the problem?

So the core problem I am facing is getting SSL support included into my binary/portable app.

A MCVE of the app is simple:

Project .pro file

QT -= gui
QT += network

CONFIG += c++11 console
CONFIG -= app_bundle

SOURCES += \
        main.cpp

INSTALLS += target

Project main.cpp

#include <QCoreApplication>
#include <QSslSocket>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    qDebug() << "Is SSL Enabled? " << QSslSocket::supportsSsl();
    qDebug() << "SSL Library Build Version (Qt compiled against): " << QSslSocket::sslLibraryBuildVersionString();
    qDebug() << "SSL Library Version String (available locally): " << QSslSocket::sslLibraryVersionString();

    return a.exec();
}

    Is SSL Enabled?  true
    SSL Library Build Version (Qt compiled against):  "OpenSSL 1.1.1d  10 Sep 2019"
    SSL Library Version String (available locally):  "OpenSSL 1.1.1d  10 Sep 2019"

Info of Dev Machine

    C:\Users\cybex>echo %PATH%
    C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Strawberry\c\bin;C:\Strawberry\perl\site\bin;C:\Strawberry\perl\bin

    C:\Users\cybex>openssl
    WARNING: can't open config file: /z/extlib/_openssl_/ssl/openssl.cnf
    OpenSSL> version
    OpenSSL 1.0.2g  1 Mar 2016

    Is SSL Enabled?  false
    SSL Library Build Version (Qt compiled against):  "OpenSSL 1.1.1d  10 Sep 2019"
    SSL Library Version String (available locally):  ""

Info of Test Machine (Completely fresh install - Windows 10 x86)

    C:\Users\cybex>echo %PATH%
    C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\
    C:\Users\cybex>openssl
    'openssl' is not recognized as an internal or external command,
    operable program or batch file.

    Is SSL Enabled?  false
    SSL Library Build Version (Qt compiled against):  "OpenSSL 1.1.1d  10 Sep 2019"
    SSL Library Version String (available locally):  ""

Info of Test Machine (Windows 7 x64 laptop with drivers installed)

    C:\Users\Home>echo %PATH%
    C:\Program Files (x86)\OpenSSL\libs;C:\Program Files (x86)\Intel\iCLS Client\;C:\Program Files\Intel\iCLS Client\;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\Intel\OpenCL SDK\2.0\bin\x86;C:\Program Files (x86)\Intel\OpenCL SDK\2.0\bin\x64;C:\Program Files\Intel\WiFi\bin\;C:\Program Files\Common Files\Intel\WirelessCommon\;C:\Program Files\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files (x86)\Intel\OpenCL SDK\2.0\bin\x86;C:\Program Files (x86)\Intel\OpenCL SDK\2.0\bin\x64;C:\Program Files (x86)\OpenSSL\libs;C:\Program Files\Intel\WiFi\bin\;C:\Program Files\Common Files\Intel\WirelessCommon\
    C:\Users\Home>openssl
    'openssl' is not recognized as an internal or external command, operable program or batch file.

By look at the above results, I conclude that installing OpenSSL solves the problem. Good, but I want need to have it included in my portable app.

In achieving this, I am required to

  1. Compile Qt statically with OpenSSL support

I have done this with the help of this script adapted from ps1 powershell script found here on Qt's wiki. I made additions for:

The configuration is as follows:

cmd /C "configure.bat -static -debug-and-release -platform win32-g++ -prefix $QtDir `
        -qt-zlib -qt-pcre -qt-libpng -qt-libjpeg -qt-freetype -opengl desktop -sql-sqlite -ssl -openssl -I $($OPENSSL_HOME)\include -L$($OPENSSL_HOME)\lib\MinGW`
        -opensource -confirm-license `
        -make libs -nomake tools -nomake examples -nomake tests -v"
cmd /C "mingw32-make -k -j$($threads)"

Note 1:

I am using -openssl and not -openssl-linked. I have tried several variations of builing Qt with both -openssl and -openssl-linked. -openssl-linked could never successfully build, see this post I made as to the reason why.

Note 2:

The only successful static Qt compilation I had working was with -ssl -openssl configuration flags enabled

OpenSSL installation is at

`$OPENSSL_HOME = "C:\OpenSSL-Win32"` 

where I am using the MinGW libraries, found in

`$OPENSSL_HOME = "C:\OpenSSL-Win32\lib\MinGW",`

with the files

Directory: C:\OpenSSL-Win32\lib\MinGW

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       2019/09/11     18:11        3347286 libcrypto.a
-a----       2019/09/11     18:10         109020 libcrypto.def
-a----       2019/09/11     18:11         385126 libssl.a
-a----       2019/09/11     18:10          14033 libssl.def
  1. Add link project .pro to OpenSSL libraries

I added the OpenSSL libraries to the .pro file (using the precompiled Qt built against OpenSSL 1.1.1d - shown above)

QT -= gui
QT += network

INCLUDEPATH += "C:\OpenSSL-Win32\include"
LIBS += -L"C:\OpenSSL-Win32\lib\MinGW\libssl.a"
LIBS += -L"C:\OpenSSL-Win32\lib\MinGW\libcrypto.a"

CONFIG += c++11 console
CONFIG -= app_bundle

SOURCES += \
        main.cpp

INSTALLS += target

Note 3

The binary size with and without the linked libraries above remains the same size

The LDD output of the binary (on my dev machine) with libraries added above is:

Start-Process -PassThru .\SSL-Test.exe | Get-Process -Module

   Size(K) ModuleName                                         FileName
   ------- ----------                                         --------
      6280 SSL-Test.exe                                       C:\Users\cybex\QtProjects\build-SSL-Test-Desktop_Qt_Op...
      1512 ntdll.dll                                          C:\Windows\SYSTEM32\ntdll.dll
       596 KERNEL32.DLL                                       C:\Windows\system32\KERNEL32.DLL
      1500 KERNELBASE.dll                                     C:\Windows\system32\KERNELBASE.dll

The LDD output of the binary (on my Windows 10 x86 test machine) with libraries added above is:

Start-Process -PassThru .\SSL-Test.exe | Get-Process -Module

   Size(K) ModuleName                                         FileName
   ------- ----------                                         --------
      6280 SSL-Test.exe                                       C:\Users\cybex\Desktop\SSL-Test.exe
      1512 ntdll.dll                                          C:\Windows\SYSTEM32\ntdll.dll
       596 KERNEL32.DLL                                       C:\Windows\system32\KERNEL32.DLL
      1500 KERNELBASE.dll                                     C:\Windows\system32\KERNELBASE.dll

Both SSL info outputs are the same

The output when requesting a SSL connection on Non-Dev machines are

QSslSocket::connectToHostEncrypted: TLS initialization failed

which is the result of the OpenSSL libary not being included.

So basically, adding a static OpenSSL library to the project file does not work or am I doing it incorrectly?

Upvotes: 1

Views: 1587

Answers (2)

dejoma
dejoma

Reputation: 504

I think you need to install an openSSL on your test machine, can do that from here https://code.google.com/archive/p/openssl-for-windows/downloads

Found in this topic

Upvotes: -1

Alexander V
Alexander V

Reputation: 8698

OpenSSL Thread Local Storage is predicated by the "library loaded" per Qt source code. Then you need to make sure either the library statically linked with your executable OR accessible through the path.

if (!supportsSsl()) {
    qCWarning(lcSsl, "QSslSocket::connectToHostEncrypted: TLS initialization failed");
    d->setErrorAndEmit(QAbstractSocket::SslInternalError, tr("TLS initialization failed"));
    return;
}

and what about supportsSsl()?

/*!
    \internal

    Does the minimum amount of initialization to determine whether SSL
    is supported or not.
*/

bool QSslSocketPrivate::supportsSsl()
{
    return ensureLibraryLoaded();
}

But that "library loaded" is a bit "deeper" concept per Qt source code here:

bool QSslSocketPrivate::ensureLibraryLoaded()
{
    if (!q_resolveOpenSslSymbols())
        return false;

    const QMutexLocker locker(qt_opensslInitMutex);

    if (!s_libraryLoaded) {
        // Initialize OpenSSL.
        if (q_OPENSSL_init_ssl(0, nullptr) != 1)
            return false;
        q_SSL_load_error_strings();
        q_OpenSSL_add_all_algorithms();

        QSslSocketBackendPrivate::s_indexForSSLExtraData
            = q_CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL, 0L, nullptr, nullptr,
                                        nullptr, nullptr);

        // Initialize OpenSSL's random seed.
        if (!q_RAND_status()) {
            qWarning("Random number generator not seeded, disabling SSL support");
            return false;
        }

        s_libraryLoaded = true;
    }
    return true;
}

As long as this is not a remote debug session, and the answer to this question matters you need to build Qt library in DEBUG mode with symbols (or get ready to use ones for the DEBUG build) and then simply put a breakpoint in this function and find the last detail preventing your Qt application from using OpenSSL.

The answer from the debugger should point to the reason of this "TLS initialization failed".

Upvotes: 0

Related Questions